diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c6b8237a7f..a3fc2893910 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14713,7 +14713,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (iife) { return !node.type && !node.dotDotDotToken && - node.parent.parameters.indexOf(node) >= iife.arguments.length; + node.parent.parameters.indexOf(node) >= getEffectiveCallArguments(iife).length; } return false; @@ -35287,14 +35287,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeOfParameter(symbol: Symbol) { - const type = getTypeOfSymbol(symbol); - if (strictNullChecks) { - const declaration = symbol.valueDeclaration; - if (declaration && hasInitializer(declaration)) { - return getOptionalType(type); - } - } - return type; + const declaration = symbol.valueDeclaration; + return addOptionality( + getTypeOfSymbol(symbol), + /*isProperty*/ false, + /*isOptional*/ !!declaration && (hasInitializer(declaration) || isOptionalDeclaration(declaration)), + ); } function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String; @@ -35587,11 +35585,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function assignParameterType(parameter: Symbol, type?: Type) { + function assignParameterType(parameter: Symbol, contextualType?: Type) { const links = getSymbolLinks(parameter); if (!links.type) { const declaration = parameter.valueDeclaration as ParameterDeclaration | undefined; - links.type = type || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter)); + links.type = addOptionality( + contextualType || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter)), + /*isProperty*/ false, + /*isOptional*/ !!declaration && !declaration.initializer && isOptionalDeclaration(declaration), + ); if (declaration && declaration.name.kind !== SyntaxKind.Identifier) { // if inference didn't come up with anything but unknown, fall back to the binding pattern if present. if (links.type === unknownType) { @@ -35600,8 +35602,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { assignBindingElementTypes(declaration.name, links.type); } } - else if (type) { - Debug.assertEqual(links.type, type, "Parameter symbol already has a cached type which differs from newly assigned type"); + else if (contextualType) { + Debug.assertEqual(links.type, contextualType, "Parameter symbol already has a cached type which differs from newly assigned type"); } } diff --git a/tests/baselines/reference/argumentsReferenceInFunction1_Js.errors.txt b/tests/baselines/reference/argumentsReferenceInFunction1_Js.errors.txt new file mode 100644 index 00000000000..507a3f56392 --- /dev/null +++ b/tests/baselines/reference/argumentsReferenceInFunction1_Js.errors.txt @@ -0,0 +1,24 @@ +index.js(1,25): error TS7006: Parameter 'f' implicitly has an 'any' type. +index.js(13,29): error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[any?, ...any[]]'. + + +==== index.js (2 errors) ==== + const format = function(f) { + ~ +!!! error TS7006: Parameter 'f' implicitly has an 'any' type. + var str = ''; + var i = 1; + var args = arguments; + var len = args.length; + for (var x = args[i]; i < len; x = args[++i]) { + str += ' ' + x; + } + return str; + }; + + const debuglog = function() { + return format.apply(null, arguments); + ~~~~~~~~~ +!!! error TS2345: Argument of type 'IArguments' is not assignable to parameter of type '[any?, ...any[]]'. + }; + \ No newline at end of file diff --git a/tests/baselines/reference/argumentsReferenceInFunction1_Js.symbols b/tests/baselines/reference/argumentsReferenceInFunction1_Js.symbols new file mode 100644 index 00000000000..548541a72ad --- /dev/null +++ b/tests/baselines/reference/argumentsReferenceInFunction1_Js.symbols @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/argumentsReferenceInFunction1_Js.ts] //// + +=== index.js === +const format = function(f) { +>format : Symbol(format, Decl(index.js, 0, 5)) +>f : Symbol(f, Decl(index.js, 0, 24)) + + var str = ''; +>str : Symbol(str, Decl(index.js, 1, 5)) + + var i = 1; +>i : Symbol(i, Decl(index.js, 2, 5)) + + var args = arguments; +>args : Symbol(args, Decl(index.js, 3, 5)) +>arguments : Symbol(arguments) + + var len = args.length; +>len : Symbol(len, Decl(index.js, 4, 5)) +>args.length : Symbol(IArguments.length, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(index.js, 3, 5)) +>length : Symbol(IArguments.length, Decl(lib.es5.d.ts, --, --)) + + for (var x = args[i]; i < len; x = args[++i]) { +>x : Symbol(x, Decl(index.js, 5, 10)) +>args : Symbol(args, Decl(index.js, 3, 5)) +>i : Symbol(i, Decl(index.js, 2, 5)) +>i : Symbol(i, Decl(index.js, 2, 5)) +>len : Symbol(len, Decl(index.js, 4, 5)) +>x : Symbol(x, Decl(index.js, 5, 10)) +>args : Symbol(args, Decl(index.js, 3, 5)) +>i : Symbol(i, Decl(index.js, 2, 5)) + + str += ' ' + x; +>str : Symbol(str, Decl(index.js, 1, 5)) +>x : Symbol(x, Decl(index.js, 5, 10)) + } + return str; +>str : Symbol(str, Decl(index.js, 1, 5)) + +}; + +const debuglog = function() { +>debuglog : Symbol(debuglog, Decl(index.js, 11, 5)) + + return format.apply(null, arguments); +>format.apply : Symbol(CallableFunction.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>format : Symbol(format, Decl(index.js, 0, 5)) +>apply : Symbol(CallableFunction.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arguments : Symbol(arguments) + +}; + diff --git a/tests/baselines/reference/argumentsReferenceInFunction1_Js.types b/tests/baselines/reference/argumentsReferenceInFunction1_Js.types new file mode 100644 index 00000000000..53677cd4053 --- /dev/null +++ b/tests/baselines/reference/argumentsReferenceInFunction1_Js.types @@ -0,0 +1,66 @@ +//// [tests/cases/compiler/argumentsReferenceInFunction1_Js.ts] //// + +=== index.js === +const format = function(f) { +>format : (f: any, ...args: any[]) => string +>function(f) { var str = ''; var i = 1; var args = arguments; var len = args.length; for (var x = args[i]; i < len; x = args[++i]) { str += ' ' + x; } return str;} : (f: any, ...args: any[]) => string +>f : any + + var str = ''; +>str : string +>'' : "" + + var i = 1; +>i : number +>1 : 1 + + var args = arguments; +>args : IArguments +>arguments : IArguments + + var len = args.length; +>len : number +>args.length : number +>args : IArguments +>length : number + + for (var x = args[i]; i < len; x = args[++i]) { +>x : any +>args[i] : any +>args : IArguments +>i : number +>i < len : boolean +>i : number +>len : number +>x = args[++i] : any +>x : any +>args[++i] : any +>args : IArguments +>++i : number +>i : number + + str += ' ' + x; +>str += ' ' + x : string +>str : string +>' ' + x : string +>' ' : " " +>x : any + } + return str; +>str : string + +}; + +const debuglog = function() { +>debuglog : (...args: any[]) => string +>function() { return format.apply(null, arguments);} : (...args: any[]) => string + + return format.apply(null, arguments); +>format.apply(null, arguments) : string +>format.apply : { (this: (this: T) => R, thisArg: T): R; (this: (this: T, ...args: A) => R, thisArg: T, args: A): R; } +>format : (f: any, ...args: any[]) => string +>apply : { (this: (this: T) => R, thisArg: T): R; (this: (this: T, ...args: A) => R, thisArg: T, args: A): R; } +>arguments : IArguments + +}; + diff --git a/tests/baselines/reference/contextuallyTypedIifeStrict.errors.txt b/tests/baselines/reference/contextuallyTypedIifeStrict.errors.txt index cde2a4aed38..4f16f08ec21 100644 --- a/tests/baselines/reference/contextuallyTypedIifeStrict.errors.txt +++ b/tests/baselines/reference/contextuallyTypedIifeStrict.errors.txt @@ -23,7 +23,7 @@ contextuallyTypedIifeStrict.ts(16,17): error TS18048: 'o' is possibly 'undefined ((k?) => k + 1)(); ~ !!! error TS18048: 'k' is possibly 'undefined'. - ((l, o?) => l + o)(12); // o should be any + ((l, o?) => l + o)(12); ~ !!! error TS18048: 'o' is possibly 'undefined'. // rest parameters diff --git a/tests/baselines/reference/contextuallyTypedIifeStrict.js b/tests/baselines/reference/contextuallyTypedIifeStrict.js index d080a4a87d5..ebbadce1865 100644 --- a/tests/baselines/reference/contextuallyTypedIifeStrict.js +++ b/tests/baselines/reference/contextuallyTypedIifeStrict.js @@ -16,7 +16,7 @@ // optional parameters ((j?) => j + 1)(12); ((k?) => k + 1)(); -((l, o?) => l + o)(12); // o should be any +((l, o?) => l + o)(12); // rest parameters ((...numbers) => numbers.every(n => n > 0))(5,6,7); ((...mixed) => mixed.every(n => !!n))(5,'oops','oh no'); @@ -57,7 +57,7 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } }); // optional parameters (function (j) { return j + 1; })(12); (function (k) { return k + 1; })(); -(function (l, o) { return l + o; })(12); // o should be any +(function (l, o) { return l + o; })(12); // rest parameters (function () { var numbers = []; diff --git a/tests/baselines/reference/contextuallyTypedIifeStrict.symbols b/tests/baselines/reference/contextuallyTypedIifeStrict.symbols index 56608baed0b..d08c670ddf0 100644 --- a/tests/baselines/reference/contextuallyTypedIifeStrict.symbols +++ b/tests/baselines/reference/contextuallyTypedIifeStrict.symbols @@ -40,7 +40,7 @@ >k : Symbol(k, Decl(contextuallyTypedIifeStrict.ts, 14, 2)) >k : Symbol(k, Decl(contextuallyTypedIifeStrict.ts, 14, 2)) -((l, o?) => l + o)(12); // o should be any +((l, o?) => l + o)(12); >l : Symbol(l, Decl(contextuallyTypedIifeStrict.ts, 15, 2)) >o : Symbol(o, Decl(contextuallyTypedIifeStrict.ts, 15, 4)) >l : Symbol(l, Decl(contextuallyTypedIifeStrict.ts, 15, 2)) diff --git a/tests/baselines/reference/contextuallyTypedIifeStrict.types b/tests/baselines/reference/contextuallyTypedIifeStrict.types index bee372f7a92..b124927c31b 100644 --- a/tests/baselines/reference/contextuallyTypedIifeStrict.types +++ b/tests/baselines/reference/contextuallyTypedIifeStrict.types @@ -89,7 +89,7 @@ >k : undefined >1 : 1 -((l, o?) => l + o)(12); // o should be any +((l, o?) => l + o)(12); >((l, o?) => l + o)(12) : any >((l, o?) => l + o) : (l: number, o?: undefined) => any >(l, o?) => l + o : (l: number, o?: undefined) => any diff --git a/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.errors.txt b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.errors.txt new file mode 100644 index 00000000000..dbf47310345 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.errors.txt @@ -0,0 +1,45 @@ +index.js(17,15): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. +index.js(28,15): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== index.js (2 errors) ==== + /** + * + * @param {number} num + */ + function acceptNum(num) {} + + /** + * @typedef {(a: string, b: number) => void} Fn + */ + + /** @type {Fn} */ + const fn1 = + /** + * @param [b] + */ + function self(a, b) { + acceptNum(b); // error + ~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + self(""); + self("", undefined); + }; + + /** @type {Fn} */ + const fn2 = + /** + * @param {number} [b] + */ + function self(a, b) { + acceptNum(b); // error + ~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + self(""); + self("", undefined); + }; + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.symbols b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.symbols new file mode 100644 index 00000000000..d269ac573e2 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.symbols @@ -0,0 +1,65 @@ +//// [tests/cases/compiler/contextuallyTypedParametersOptionalInJSDoc.ts] //// + +=== index.js === +/** + * + * @param {number} num + */ +function acceptNum(num) {} +>acceptNum : Symbol(acceptNum, Decl(index.js, 0, 0)) +>num : Symbol(num, Decl(index.js, 4, 19)) + +/** + * @typedef {(a: string, b: number) => void} Fn + */ + +/** @type {Fn} */ +const fn1 = +>fn1 : Symbol(fn1, Decl(index.js, 11, 5)) + + /** + * @param [b] + */ + function self(a, b) { +>self : Symbol(self, Decl(index.js, 11, 11)) +>a : Symbol(a, Decl(index.js, 15, 16)) +>b : Symbol(b, Decl(index.js, 15, 18)) + + acceptNum(b); // error +>acceptNum : Symbol(acceptNum, Decl(index.js, 0, 0)) +>b : Symbol(b, Decl(index.js, 15, 18)) + + self(""); +>self : Symbol(self, Decl(index.js, 11, 11)) + + self("", undefined); +>self : Symbol(self, Decl(index.js, 11, 11)) +>undefined : Symbol(undefined) + + }; + +/** @type {Fn} */ +const fn2 = +>fn2 : Symbol(fn2, Decl(index.js, 22, 5)) + + /** + * @param {number} [b] + */ + function self(a, b) { +>self : Symbol(self, Decl(index.js, 22, 11)) +>a : Symbol(a, Decl(index.js, 26, 16)) +>b : Symbol(b, Decl(index.js, 26, 18)) + + acceptNum(b); // error +>acceptNum : Symbol(acceptNum, Decl(index.js, 0, 0)) +>b : Symbol(b, Decl(index.js, 26, 18)) + + self(""); +>self : Symbol(self, Decl(index.js, 22, 11)) + + self("", undefined); +>self : Symbol(self, Decl(index.js, 22, 11)) +>undefined : Symbol(undefined) + + }; + diff --git a/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.types b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.types new file mode 100644 index 00000000000..899c9f70884 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersOptionalInJSDoc.types @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/contextuallyTypedParametersOptionalInJSDoc.ts] //// + +=== index.js === +/** + * + * @param {number} num + */ +function acceptNum(num) {} +>acceptNum : (num: number) => void +>num : number + +/** + * @typedef {(a: string, b: number) => void} Fn + */ + +/** @type {Fn} */ +const fn1 = +>fn1 : Fn + + /** + * @param [b] + */ + function self(a, b) { +>function self(a, b) { acceptNum(b); // error self(""); self("", undefined); } : (a: string, b?: number | undefined) => void +>self : (a: string, b?: number | undefined) => void +>a : string +>b : number | undefined + + acceptNum(b); // error +>acceptNum(b) : void +>acceptNum : (num: number) => void +>b : number | undefined + + self(""); +>self("") : void +>self : (a: string, b?: number | undefined) => void +>"" : "" + + self("", undefined); +>self("", undefined) : void +>self : (a: string, b?: number | undefined) => void +>"" : "" +>undefined : undefined + + }; + +/** @type {Fn} */ +const fn2 = +>fn2 : Fn + + /** + * @param {number} [b] + */ + function self(a, b) { +>function self(a, b) { acceptNum(b); // error self(""); self("", undefined); } : (a: string, b?: number | undefined) => void +>self : (a: string, b?: number | undefined) => void +>a : string +>b : number | undefined + + acceptNum(b); // error +>acceptNum(b) : void +>acceptNum : (num: number) => void +>b : number | undefined + + self(""); +>self("") : void +>self : (a: string, b?: number | undefined) => void +>"" : "" + + self("", undefined); +>self("", undefined) : void +>self : (a: string, b?: number | undefined) => void +>"" : "" +>undefined : undefined + + }; + diff --git a/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.errors.txt b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.errors.txt new file mode 100644 index 00000000000..b4e9bf7f746 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.errors.txt @@ -0,0 +1,29 @@ +contextuallyTypedParametersWithQuestionToken.ts(6,13): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. +contextuallyTypedParametersWithQuestionToken.ts(12,13): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== contextuallyTypedParametersWithQuestionToken.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/54948 + + function acceptNum(num: number) {} + + const f1: (a: string, b: number) => void = function self(a, b?) { + acceptNum(b); // error + ~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + self(""); + self("", undefined); + }; + + const f2: (a: string, b: number) => void = function self(a, b?: number) { + acceptNum(b); // error + ~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + self(""); + self("", undefined); + }; + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.symbols b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.symbols new file mode 100644 index 00000000000..faf2d4a6c51 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/contextuallyTypedParametersWithQuestionToken.ts] //// + +=== contextuallyTypedParametersWithQuestionToken.ts === +// https://github.com/microsoft/TypeScript/issues/54948 + +function acceptNum(num: number) {} +>acceptNum : Symbol(acceptNum, Decl(contextuallyTypedParametersWithQuestionToken.ts, 0, 0)) +>num : Symbol(num, Decl(contextuallyTypedParametersWithQuestionToken.ts, 2, 19)) + +const f1: (a: string, b: number) => void = function self(a, b?) { +>f1 : Symbol(f1, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 5)) +>a : Symbol(a, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 11)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 21)) +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 42)) +>a : Symbol(a, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 57)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 59)) + + acceptNum(b); // error +>acceptNum : Symbol(acceptNum, Decl(contextuallyTypedParametersWithQuestionToken.ts, 0, 0)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 59)) + + self(""); +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 42)) + + self("", undefined); +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 4, 42)) +>undefined : Symbol(undefined) + +}; + +const f2: (a: string, b: number) => void = function self(a, b?: number) { +>f2 : Symbol(f2, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 5)) +>a : Symbol(a, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 11)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 21)) +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 42)) +>a : Symbol(a, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 57)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 59)) + + acceptNum(b); // error +>acceptNum : Symbol(acceptNum, Decl(contextuallyTypedParametersWithQuestionToken.ts, 0, 0)) +>b : Symbol(b, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 59)) + + self(""); +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 42)) + + self("", undefined); +>self : Symbol(self, Decl(contextuallyTypedParametersWithQuestionToken.ts, 10, 42)) +>undefined : Symbol(undefined) + +}; + diff --git a/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.types b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.types new file mode 100644 index 00000000000..fa74f271ff1 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithQuestionToken.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/contextuallyTypedParametersWithQuestionToken.ts] //// + +=== contextuallyTypedParametersWithQuestionToken.ts === +// https://github.com/microsoft/TypeScript/issues/54948 + +function acceptNum(num: number) {} +>acceptNum : (num: number) => void +>num : number + +const f1: (a: string, b: number) => void = function self(a, b?) { +>f1 : (a: string, b: number) => void +>a : string +>b : number +>function self(a, b?) { acceptNum(b); // error self(""); self("", undefined);} : (a: string, b?: number | undefined) => void +>self : (a: string, b?: number | undefined) => void +>a : string +>b : number | undefined + + acceptNum(b); // error +>acceptNum(b) : void +>acceptNum : (num: number) => void +>b : number | undefined + + self(""); +>self("") : void +>self : (a: string, b?: number | undefined) => void +>"" : "" + + self("", undefined); +>self("", undefined) : void +>self : (a: string, b?: number | undefined) => void +>"" : "" +>undefined : undefined + +}; + +const f2: (a: string, b: number) => void = function self(a, b?: number) { +>f2 : (a: string, b: number) => void +>a : string +>b : number +>function self(a, b?: number) { acceptNum(b); // error self(""); self("", undefined);} : (a: string, b?: number) => void +>self : (a: string, b?: number) => void +>a : string +>b : number | undefined + + acceptNum(b); // error +>acceptNum(b) : void +>acceptNum : (num: number) => void +>b : number | undefined + + self(""); +>self("") : void +>self : (a: string, b?: number | undefined) => void +>"" : "" + + self("", undefined); +>self("", undefined) : void +>self : (a: string, b?: number | undefined) => void +>"" : "" +>undefined : undefined + +}; + diff --git a/tests/baselines/reference/restTuplesFromContextualTypes.types b/tests/baselines/reference/restTuplesFromContextualTypes.types index 498ae88f84d..d80a1124a0f 100644 --- a/tests/baselines/reference/restTuplesFromContextualTypes.types +++ b/tests/baselines/reference/restTuplesFromContextualTypes.types @@ -6,8 +6,8 @@ declare const t1: [number, boolean, string]; (function (a, b, c){})(...t1); >(function (a, b, c){})(...t1) : void ->(function (a, b, c){}) : (a: number, b?: boolean, c?: string) => void ->function (a, b, c){} : (a: number, b?: boolean, c?: string) => void +>(function (a, b, c){}) : (a: number, b: boolean, c: string) => void +>function (a, b, c){} : (a: number, b: boolean, c: string) => void >a : number >b : boolean >c : string @@ -33,8 +33,8 @@ declare const t1: [number, boolean, string]; (function (a, b, ...x){})(...t1); >(function (a, b, ...x){})(...t1) : void ->(function (a, b, ...x){}) : (a: number, b?: boolean, x_0: string) => void ->function (a, b, ...x){} : (a: number, b?: boolean, x_0: string) => void +>(function (a, b, ...x){}) : (a: number, b: boolean, x_0: string) => void +>function (a, b, ...x){} : (a: number, b: boolean, x_0: string) => void >a : number >b : boolean >x : [string] @@ -43,8 +43,8 @@ declare const t1: [number, boolean, string]; (function (a, b, c, ...x){})(...t1); >(function (a, b, c, ...x){})(...t1) : void ->(function (a, b, c, ...x){}) : (a: number, b?: boolean, c?: string) => void ->function (a, b, c, ...x){} : (a: number, b?: boolean, c?: string) => void +>(function (a, b, c, ...x){}) : (a: number, b: boolean, c: string) => void +>function (a, b, c, ...x){} : (a: number, b: boolean, c: string) => void >a : number >b : boolean >c : string @@ -101,8 +101,8 @@ declare const t2: [number, boolean, ...string[]]; (function (a, b, c){})(...t2); >(function (a, b, c){})(...t2) : void ->(function (a, b, c){}) : (a: number, b?: boolean, c?: string) => void ->function (a, b, c){} : (a: number, b?: boolean, c?: string) => void +>(function (a, b, c){}) : (a: number, b: boolean, c: string) => void +>function (a, b, c){} : (a: number, b: boolean, c: string) => void >a : number >b : boolean >c : string @@ -128,8 +128,8 @@ declare const t2: [number, boolean, ...string[]]; (function (a, b, ...x){})(...t2); >(function (a, b, ...x){})(...t2) : void ->(function (a, b, ...x){}) : (a: number, b?: boolean, ...x: string[]) => void ->function (a, b, ...x){} : (a: number, b?: boolean, ...x: string[]) => void +>(function (a, b, ...x){}) : (a: number, b: boolean, ...x: string[]) => void +>function (a, b, ...x){} : (a: number, b: boolean, ...x: string[]) => void >a : number >b : boolean >x : string[] @@ -138,8 +138,8 @@ declare const t2: [number, boolean, ...string[]]; (function (a, b, c, ...x){})(...t2); >(function (a, b, c, ...x){})(...t2) : void ->(function (a, b, c, ...x){}) : (a: number, b?: boolean, c?: string, ...x: string[]) => void ->function (a, b, c, ...x){} : (a: number, b?: boolean, c?: string, ...x: string[]) => void +>(function (a, b, c, ...x){}) : (a: number, b: boolean, c: string, ...x: string[]) => void +>function (a, b, c, ...x){} : (a: number, b: boolean, c: string, ...x: string[]) => void >a : number >b : boolean >c : string @@ -196,8 +196,8 @@ declare const t3: [boolean, ...string[]]; (function (a, b, c){})(1, ...t3); >(function (a, b, c){})(1, ...t3) : void ->(function (a, b, c){}) : (a: number, b: boolean, c?: string) => void ->function (a, b, c){} : (a: number, b: boolean, c?: string) => void +>(function (a, b, c){}) : (a: number, b: boolean, c: string) => void +>function (a, b, c){} : (a: number, b: boolean, c: string) => void >a : number >b : boolean >c : string @@ -237,8 +237,8 @@ declare const t3: [boolean, ...string[]]; (function (a, b, c, ...x){})(1, ...t3); >(function (a, b, c, ...x){})(1, ...t3) : void ->(function (a, b, c, ...x){}) : (a: number, b: boolean, c?: string, ...x: string[]) => void ->function (a, b, c, ...x){} : (a: number, b: boolean, c?: string, ...x: string[]) => void +>(function (a, b, c, ...x){}) : (a: number, b: boolean, c: string, ...x: string[]) => void +>function (a, b, c, ...x){} : (a: number, b: boolean, c: string, ...x: string[]) => void >a : number >b : boolean >c : string @@ -470,8 +470,8 @@ declare var tuple: [number, string]; (function foo(a, b){}(...tuple)); >(function foo(a, b){}(...tuple)) : void >function foo(a, b){}(...tuple) : void ->function foo(a, b){} : (a: number, b?: string) => void ->foo : (a: number, b?: string) => void +>function foo(a, b){} : (a: number, b: string) => void +>foo : (a: number, b: string) => void >a : number >b : string >...tuple : string | number diff --git a/tests/cases/compiler/argumentsReferenceInFunction1_Js.ts b/tests/cases/compiler/argumentsReferenceInFunction1_Js.ts new file mode 100644 index 00000000000..17cedde3bac --- /dev/null +++ b/tests/cases/compiler/argumentsReferenceInFunction1_Js.ts @@ -0,0 +1,20 @@ +// @strict: true +// @checkJs: true +// @noEmit: true + +// @filename: index.js + +const format = function(f) { + var str = ''; + var i = 1; + var args = arguments; + var len = args.length; + for (var x = args[i]; i < len; x = args[++i]) { + str += ' ' + x; + } + return str; +}; + +const debuglog = function() { + return format.apply(null, arguments); +}; diff --git a/tests/cases/compiler/contextuallyTypedParametersOptionalInJSDoc.ts b/tests/cases/compiler/contextuallyTypedParametersOptionalInJSDoc.ts new file mode 100644 index 00000000000..32d4e2e41a7 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedParametersOptionalInJSDoc.ts @@ -0,0 +1,37 @@ +// @strict: true +// @checkJs: true +// @noEmit: true + +// @filename: index.js + +/** + * + * @param {number} num + */ +function acceptNum(num) {} + +/** + * @typedef {(a: string, b: number) => void} Fn + */ + +/** @type {Fn} */ +const fn1 = + /** + * @param [b] + */ + function self(a, b) { + acceptNum(b); // error + self(""); + self("", undefined); + }; + +/** @type {Fn} */ +const fn2 = + /** + * @param {number} [b] + */ + function self(a, b) { + acceptNum(b); // error + self(""); + self("", undefined); + }; diff --git a/tests/cases/compiler/contextuallyTypedParametersWithQuestionToken.ts b/tests/cases/compiler/contextuallyTypedParametersWithQuestionToken.ts new file mode 100644 index 00000000000..32d1a97048f --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedParametersWithQuestionToken.ts @@ -0,0 +1,18 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/54948 + +function acceptNum(num: number) {} + +const f1: (a: string, b: number) => void = function self(a, b?) { + acceptNum(b); // error + self(""); + self("", undefined); +}; + +const f2: (a: string, b: number) => void = function self(a, b?: number) { + acceptNum(b); // error + self(""); + self("", undefined); +}; diff --git a/tests/cases/conformance/expressions/functions/contextuallyTypedIifeStrict.ts b/tests/cases/conformance/expressions/functions/contextuallyTypedIifeStrict.ts index 04951beb9f0..697c6e6581c 100644 --- a/tests/cases/conformance/expressions/functions/contextuallyTypedIifeStrict.ts +++ b/tests/cases/conformance/expressions/functions/contextuallyTypedIifeStrict.ts @@ -14,7 +14,7 @@ // optional parameters ((j?) => j + 1)(12); ((k?) => k + 1)(); -((l, o?) => l + o)(12); // o should be any +((l, o?) => l + o)(12); // rest parameters ((...numbers) => numbers.every(n => n > 0))(5,6,7); ((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');