Make contextually-typed parameter with question token optional (#54960)

This commit is contained in:
Mateusz Burzyński 2023-08-22 00:01:07 +02:00 committed by GitHub
parent 3af710e414
commit e99508b863
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 587 additions and 37 deletions

View File

@ -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");
}
}

View File

@ -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[]]'.
};

View File

@ -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)
};

View File

@ -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 : { <T, R>(this: (this: T) => R, thisArg: T): R; <T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R; }
>format : (f: any, ...args: any[]) => string
>apply : { <T, R>(this: (this: T) => R, thisArg: T): R; <T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R; }
>arguments : IArguments
};

View File

@ -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

View File

@ -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 = [];

View File

@ -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))

View File

@ -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

View File

@ -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);
};

View File

@ -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)
};

View File

@ -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
};

View File

@ -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);
};

View File

@ -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)
};

View File

@ -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
};

View File

@ -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

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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');