Merge pull request #8730 from Microsoft/destructureOptionalParameter
Fix destructuring of optional parameters with --strictNullChecks
This commit is contained in:
commit
92d465d01f
5 changed files with 232 additions and 7 deletions
|
@ -2745,7 +2745,7 @@ namespace ts {
|
|||
// assigned by contextual typing.
|
||||
function getTypeForBindingElementParent(node: VariableLikeDeclaration) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node);
|
||||
return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false);
|
||||
}
|
||||
|
||||
function getTextOfPropertyName(name: PropertyName): string {
|
||||
|
@ -2885,7 +2885,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
|
||||
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type {
|
||||
if (declaration.flags & NodeFlags.JavaScriptFile) {
|
||||
// If this is a variable in a JavaScript file, then use the JSDoc type (if it has
|
||||
// one as its type), otherwise fallback to the below standard TS codepaths to
|
||||
|
@ -2915,7 +2915,7 @@ namespace ts {
|
|||
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ !!declaration.questionToken);
|
||||
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
|
@ -2937,13 +2937,13 @@ namespace ts {
|
|||
? getContextuallyTypedThisType(func)
|
||||
: getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
if (type) {
|
||||
return addOptionality(type, /*optional*/ !!declaration.questionToken);
|
||||
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ !!declaration.questionToken);
|
||||
return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
// If it is a short-hand property assignment, use the type of the identifier
|
||||
|
@ -3046,7 +3046,7 @@ namespace ts {
|
|||
// binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the
|
||||
// tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string.
|
||||
function getWidenedTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, reportErrors?: boolean): Type {
|
||||
let type = getTypeForVariableLikeDeclaration(declaration);
|
||||
let type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true);
|
||||
if (type) {
|
||||
if (reportErrors) {
|
||||
reportErrorsFromWidening(declaration, type);
|
||||
|
@ -16903,7 +16903,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
if (isBindingPattern(node)) {
|
||||
return getTypeForVariableLikeDeclaration(<VariableLikeDeclaration>node.parent);
|
||||
return getTypeForVariableLikeDeclaration(<VariableLikeDeclaration>node.parent, /*includeOptionality*/ true);
|
||||
}
|
||||
|
||||
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
|
||||
|
|
59
tests/baselines/reference/destructureOptionalParameter.js
Normal file
59
tests/baselines/reference/destructureOptionalParameter.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
//// [destructureOptionalParameter.ts]
|
||||
|
||||
declare function f1({ a, b }?: { a: number, b: string }): void;
|
||||
|
||||
function f2({ a, b }: { a: number, b: number } = { a: 0, b: 0 }) {
|
||||
a;
|
||||
b;
|
||||
}
|
||||
|
||||
// Repro from #8681
|
||||
|
||||
interface Type { t: void }
|
||||
interface QueryMetadata { q: void }
|
||||
|
||||
interface QueryMetadataFactory {
|
||||
(selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): ParameterDecorator;
|
||||
new (selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): QueryMetadata;
|
||||
}
|
||||
|
||||
|
||||
//// [destructureOptionalParameter.js]
|
||||
function f2(_a) {
|
||||
var _b = _a === void 0 ? { a: 0, b: 0 } : _a, a = _b.a, b = _b.b;
|
||||
a;
|
||||
b;
|
||||
}
|
||||
|
||||
|
||||
//// [destructureOptionalParameter.d.ts]
|
||||
declare function f1({a, b}?: {
|
||||
a: number;
|
||||
b: string;
|
||||
}): void;
|
||||
declare function f2({a, b}?: {
|
||||
a: number;
|
||||
b: number;
|
||||
}): void;
|
||||
interface Type {
|
||||
t: void;
|
||||
}
|
||||
interface QueryMetadata {
|
||||
q: void;
|
||||
}
|
||||
interface QueryMetadataFactory {
|
||||
(selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): ParameterDecorator;
|
||||
new (selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): QueryMetadata;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
=== tests/cases/compiler/destructureOptionalParameter.ts ===
|
||||
|
||||
declare function f1({ a, b }?: { a: number, b: string }): void;
|
||||
>f1 : Symbol(f1, Decl(destructureOptionalParameter.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 1, 21))
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 1, 24))
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 1, 32))
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 1, 43))
|
||||
|
||||
function f2({ a, b }: { a: number, b: number } = { a: 0, b: 0 }) {
|
||||
>f2 : Symbol(f2, Decl(destructureOptionalParameter.ts, 1, 63))
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 3, 13))
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 3, 16))
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 3, 23))
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 3, 34))
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 3, 50))
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 3, 56))
|
||||
|
||||
a;
|
||||
>a : Symbol(a, Decl(destructureOptionalParameter.ts, 3, 13))
|
||||
|
||||
b;
|
||||
>b : Symbol(b, Decl(destructureOptionalParameter.ts, 3, 16))
|
||||
}
|
||||
|
||||
// Repro from #8681
|
||||
|
||||
interface Type { t: void }
|
||||
>Type : Symbol(Type, Decl(destructureOptionalParameter.ts, 6, 1))
|
||||
>t : Symbol(Type.t, Decl(destructureOptionalParameter.ts, 10, 16))
|
||||
|
||||
interface QueryMetadata { q: void }
|
||||
>QueryMetadata : Symbol(QueryMetadata, Decl(destructureOptionalParameter.ts, 10, 26))
|
||||
>q : Symbol(QueryMetadata.q, Decl(destructureOptionalParameter.ts, 11, 25))
|
||||
|
||||
interface QueryMetadataFactory {
|
||||
>QueryMetadataFactory : Symbol(QueryMetadataFactory, Decl(destructureOptionalParameter.ts, 11, 35))
|
||||
|
||||
(selector: Type | string, {descendants, read}?: {
|
||||
>selector : Symbol(selector, Decl(destructureOptionalParameter.ts, 14, 5))
|
||||
>Type : Symbol(Type, Decl(destructureOptionalParameter.ts, 6, 1))
|
||||
>descendants : Symbol(descendants, Decl(destructureOptionalParameter.ts, 14, 31))
|
||||
>read : Symbol(read, Decl(destructureOptionalParameter.ts, 14, 43))
|
||||
|
||||
descendants?: boolean;
|
||||
>descendants : Symbol(descendants, Decl(destructureOptionalParameter.ts, 14, 53))
|
||||
|
||||
read?: any;
|
||||
>read : Symbol(read, Decl(destructureOptionalParameter.ts, 15, 30))
|
||||
|
||||
}): ParameterDecorator;
|
||||
>ParameterDecorator : Symbol(ParameterDecorator, Decl(lib.d.ts, --, --))
|
||||
|
||||
new (selector: Type | string, {descendants, read}?: {
|
||||
>selector : Symbol(selector, Decl(destructureOptionalParameter.ts, 18, 9))
|
||||
>Type : Symbol(Type, Decl(destructureOptionalParameter.ts, 6, 1))
|
||||
>descendants : Symbol(descendants, Decl(destructureOptionalParameter.ts, 18, 35))
|
||||
>read : Symbol(read, Decl(destructureOptionalParameter.ts, 18, 47))
|
||||
|
||||
descendants?: boolean;
|
||||
>descendants : Symbol(descendants, Decl(destructureOptionalParameter.ts, 18, 57))
|
||||
|
||||
read?: any;
|
||||
>read : Symbol(read, Decl(destructureOptionalParameter.ts, 19, 30))
|
||||
|
||||
}): QueryMetadata;
|
||||
>QueryMetadata : Symbol(QueryMetadata, Decl(destructureOptionalParameter.ts, 10, 26))
|
||||
}
|
||||
|
72
tests/baselines/reference/destructureOptionalParameter.types
Normal file
72
tests/baselines/reference/destructureOptionalParameter.types
Normal file
|
@ -0,0 +1,72 @@
|
|||
=== tests/cases/compiler/destructureOptionalParameter.ts ===
|
||||
|
||||
declare function f1({ a, b }?: { a: number, b: string }): void;
|
||||
>f1 : ({a, b}?: { a: number; b: string; } | undefined) => void
|
||||
>a : number
|
||||
>b : string
|
||||
>a : number
|
||||
>b : string
|
||||
|
||||
function f2({ a, b }: { a: number, b: number } = { a: 0, b: 0 }) {
|
||||
>f2 : ({a, b}?: { a: number; b: number; }) => void
|
||||
>a : number
|
||||
>b : number
|
||||
>a : number
|
||||
>b : number
|
||||
>{ a: 0, b: 0 } : { a: number; b: number; }
|
||||
>a : number
|
||||
>0 : number
|
||||
>b : number
|
||||
>0 : number
|
||||
|
||||
a;
|
||||
>a : number
|
||||
|
||||
b;
|
||||
>b : number
|
||||
}
|
||||
|
||||
// Repro from #8681
|
||||
|
||||
interface Type { t: void }
|
||||
>Type : Type
|
||||
>t : void
|
||||
|
||||
interface QueryMetadata { q: void }
|
||||
>QueryMetadata : QueryMetadata
|
||||
>q : void
|
||||
|
||||
interface QueryMetadataFactory {
|
||||
>QueryMetadataFactory : QueryMetadataFactory
|
||||
|
||||
(selector: Type | string, {descendants, read}?: {
|
||||
>selector : Type | string
|
||||
>Type : Type
|
||||
>descendants : boolean | undefined
|
||||
>read : any
|
||||
|
||||
descendants?: boolean;
|
||||
>descendants : boolean | undefined
|
||||
|
||||
read?: any;
|
||||
>read : any
|
||||
|
||||
}): ParameterDecorator;
|
||||
>ParameterDecorator : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void
|
||||
|
||||
new (selector: Type | string, {descendants, read}?: {
|
||||
>selector : Type | string
|
||||
>Type : Type
|
||||
>descendants : boolean | undefined
|
||||
>read : any
|
||||
|
||||
descendants?: boolean;
|
||||
>descendants : boolean | undefined
|
||||
|
||||
read?: any;
|
||||
>read : any
|
||||
|
||||
}): QueryMetadata;
|
||||
>QueryMetadata : QueryMetadata
|
||||
}
|
||||
|
25
tests/cases/compiler/destructureOptionalParameter.ts
Normal file
25
tests/cases/compiler/destructureOptionalParameter.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
// @strictNullChecks: true
|
||||
// @declaration: true
|
||||
|
||||
declare function f1({ a, b }?: { a: number, b: string }): void;
|
||||
|
||||
function f2({ a, b }: { a: number, b: number } = { a: 0, b: 0 }) {
|
||||
a;
|
||||
b;
|
||||
}
|
||||
|
||||
// Repro from #8681
|
||||
|
||||
interface Type { t: void }
|
||||
interface QueryMetadata { q: void }
|
||||
|
||||
interface QueryMetadataFactory {
|
||||
(selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): ParameterDecorator;
|
||||
new (selector: Type | string, {descendants, read}?: {
|
||||
descendants?: boolean;
|
||||
read?: any;
|
||||
}): QueryMetadata;
|
||||
}
|
Loading…
Reference in a new issue