mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Destructuring declaration prefers type annotation type (#25282)
* Destructuring declaration prefers type annotation type Previously, getTypeForBindingElement would always union the declarations type and the type of the default initializer. Now, if the declaration has a type annotation, it does not union with the initializer type. The type annotation's type is the one used. * Small cleanup in parentDeclarationHasTypeAnnotation * Refactoring based on PR comments * Combine getCombined*Flags into a single helper function Retain the individual functions since they are used a lot. * Remove unneeded temp
This commit is contained in:
parent
950593b669
commit
5c2eeb20b1
@ -4161,7 +4161,7 @@ namespace ts {
|
||||
}
|
||||
const parent = getDeclarationContainer(node);
|
||||
// If the node is not exported or it is not ambient module element (except import declaration)
|
||||
if (!(getCombinedModifierFlags(node) & ModifierFlags.Export) &&
|
||||
if (!(getCombinedModifierFlags(node as Declaration) & ModifierFlags.Export) &&
|
||||
!(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient)) {
|
||||
return isGlobalSourceFile(parent);
|
||||
}
|
||||
@ -4525,7 +4525,7 @@ namespace ts {
|
||||
if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
|
||||
type = getTypeWithFacts(type, TypeFacts.NEUndefined);
|
||||
}
|
||||
return declaration.initializer ?
|
||||
return declaration.initializer && !getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration)) ?
|
||||
getUnionType([type, checkExpressionCached(declaration.initializer)], UnionReduction.Subtype) :
|
||||
type;
|
||||
}
|
||||
@ -22096,7 +22096,7 @@ namespace ts {
|
||||
return hasModifier(node, ModifierFlags.Private) && !!(node.flags & NodeFlags.Ambient);
|
||||
}
|
||||
|
||||
function getEffectiveDeclarationFlags(n: Node, flagsToCheck: ModifierFlags): ModifierFlags {
|
||||
function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags {
|
||||
let flags = getCombinedModifierFlags(n);
|
||||
|
||||
// children of classes (even ambient classes) should not be marked as ambient or export
|
||||
|
||||
@ -903,7 +903,7 @@ namespace ts {
|
||||
|
||||
export function isConst(node: Node): boolean {
|
||||
return !!(getCombinedNodeFlags(node) & NodeFlags.Const)
|
||||
|| !!(getCombinedModifierFlags(node) & ModifierFlags.Const);
|
||||
|| !!(isDeclaration(node) && getCombinedModifierFlags(node) & ModifierFlags.Const);
|
||||
}
|
||||
|
||||
export function isLet(node: Node): boolean {
|
||||
@ -4605,33 +4605,36 @@ namespace ts {
|
||||
return isEmptyBindingPattern(node.name);
|
||||
}
|
||||
|
||||
function walkUpBindingElementsAndPatterns(node: Node): Node {
|
||||
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
|
||||
node = node.parent;
|
||||
export function walkUpBindingElementsAndPatterns(binding: BindingElement): VariableDeclaration | ParameterDeclaration {
|
||||
let node = binding.parent;
|
||||
while (isBindingElement(node.parent)) {
|
||||
node = node.parent.parent;
|
||||
}
|
||||
|
||||
return node;
|
||||
return node.parent;
|
||||
}
|
||||
|
||||
export function getCombinedModifierFlags(node: Node): ModifierFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
let flags = getModifierFlags(node);
|
||||
function getCombinedFlags(node: Node, getFlags: (n: Node) => number): number {
|
||||
if (isBindingElement(node)) {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
}
|
||||
let flags = getFlags(node);
|
||||
if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
flags |= getModifierFlags(node);
|
||||
flags |= getFlags(node);
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableStatement) {
|
||||
flags |= getModifierFlags(node);
|
||||
flags |= getFlags(node);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
export function getCombinedModifierFlags(node: Declaration): ModifierFlags {
|
||||
return getCombinedFlags(node, getModifierFlags);
|
||||
}
|
||||
|
||||
// Returns the node flags for this node and all relevant parent nodes. This is done so that
|
||||
// nodes like variable declarations and binding elements can returned a view of their flags
|
||||
// that includes the modifiers from their container. i.e. flags like export/declare aren't
|
||||
@ -4640,23 +4643,7 @@ namespace ts {
|
||||
// list. By calling this function, all those flags are combined so that the client can treat
|
||||
// the node as if it actually had those flags.
|
||||
export function getCombinedNodeFlags(node: Node): NodeFlags {
|
||||
node = walkUpBindingElementsAndPatterns(node);
|
||||
|
||||
let flags = node.flags;
|
||||
if (node.kind === SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
flags |= node.flags;
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (node && node.kind === SyntaxKind.VariableStatement) {
|
||||
flags |= node.flags;
|
||||
}
|
||||
|
||||
return flags;
|
||||
return getCombinedFlags(node, n => n.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1044,7 +1044,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getNodeModifiers(node: Node): string {
|
||||
const flags = getCombinedModifierFlags(node);
|
||||
const flags = isDeclaration(node) ? getCombinedModifierFlags(node) : ModifierFlags.None;
|
||||
const result: string[] = [];
|
||||
|
||||
if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
|
||||
|
||||
@ -6677,7 +6677,8 @@ declare namespace ts {
|
||||
function isParameterPropertyDeclaration(node: Node): node is ParameterPropertyDeclaration;
|
||||
function isEmptyBindingPattern(node: BindingName): node is BindingPattern;
|
||||
function isEmptyBindingElement(node: BindingElement): boolean;
|
||||
function getCombinedModifierFlags(node: Node): ModifierFlags;
|
||||
function walkUpBindingElementsAndPatterns(binding: BindingElement): VariableDeclaration | ParameterDeclaration;
|
||||
function getCombinedModifierFlags(node: Declaration): ModifierFlags;
|
||||
function getCombinedNodeFlags(node: Node): NodeFlags;
|
||||
/**
|
||||
* Checks to see if the locale is in the appropriate format,
|
||||
|
||||
@ -3175,7 +3175,8 @@ declare namespace ts {
|
||||
function isParameterPropertyDeclaration(node: Node): node is ParameterPropertyDeclaration;
|
||||
function isEmptyBindingPattern(node: BindingName): node is BindingPattern;
|
||||
function isEmptyBindingElement(node: BindingElement): boolean;
|
||||
function getCombinedModifierFlags(node: Node): ModifierFlags;
|
||||
function walkUpBindingElementsAndPatterns(binding: BindingElement): VariableDeclaration | ParameterDeclaration;
|
||||
function getCombinedModifierFlags(node: Declaration): ModifierFlags;
|
||||
function getCombinedNodeFlags(node: Node): NodeFlags;
|
||||
/**
|
||||
* Checks to see if the locale is in the appropriate format,
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,20): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,23): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,25): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,23): error TS2322: Type '{ show: (v: number) => number; }' is not assignable to type 'Show'.
|
||||
Types of property 'show' are incompatible.
|
||||
Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(21,14): error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts (7 errors) ====
|
||||
interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
}
|
||||
function ff({ nested: nestedRename = { show: v => v } }: Nested) {}
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ show: (v: number) => number; }' is not assignable to type 'Show'.
|
||||
!!! error TS2322: Types of property 'show' are incompatible.
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface StringIdentity {
|
||||
stringIdentity(s: string): string;
|
||||
}
|
||||
let { stringIdentity: id = arg => arg.length }: StringIdentity = { stringIdentity: x => x};
|
||||
~~
|
||||
!!! error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface Tuples {
|
||||
prop: [string, number];
|
||||
}
|
||||
function g({ prop = [101, 1234] }: Tuples) {}
|
||||
~~~~
|
||||
!!! error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface StringUnion {
|
||||
prop: "foo" | "bar";
|
||||
}
|
||||
function h({ prop = "baz" }: StringUnion) {}
|
||||
~~~~
|
||||
!!! error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
|
||||
@ -9,7 +9,7 @@ interface Show {
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
>f : ({ show: showRename }: Show) => void
|
||||
>show : any
|
||||
>showRename : ((x: number) => string) | ((v: number) => number)
|
||||
>showRename : (x: number) => string
|
||||
>v => v : (v: number) => number
|
||||
>v : number
|
||||
>v : number
|
||||
@ -17,7 +17,7 @@ function f({ show: showRename = v => v }: Show) {}
|
||||
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
>f2 : ({ "show": showRename }: Show) => void
|
||||
>showRename : ((x: number) => string) | ((v: number) => number)
|
||||
>showRename : (x: number) => string
|
||||
>v => v : (v: number) => number
|
||||
>v : number
|
||||
>v : number
|
||||
@ -26,7 +26,7 @@ function f2({ "show": showRename = v => v }: Show) {}
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
>f3 : ({ ["show"]: showRename }: Show) => void
|
||||
>"show" : "show"
|
||||
>showRename : ((x: number) => string) | ((v: number) => number)
|
||||
>showRename : (x: number) => string
|
||||
>v => v : (v: number) => number
|
||||
>v : number
|
||||
>v : number
|
||||
@ -42,7 +42,7 @@ interface Nested {
|
||||
function ff({ nested: nestedRename = { show: v => v } }: Nested) {}
|
||||
>ff : ({ nested: nestedRename }: Nested) => void
|
||||
>nested : any
|
||||
>nestedRename : Show | { show: (v: number) => number; }
|
||||
>nestedRename : Show
|
||||
>{ show: v => v } : { show: (v: number) => number; }
|
||||
>show : (v: number) => number
|
||||
>v => v : (v: number) => number
|
||||
@ -59,7 +59,7 @@ interface StringIdentity {
|
||||
}
|
||||
let { stringIdentity: id = arg => arg.length }: StringIdentity = { stringIdentity: x => x};
|
||||
>stringIdentity : any
|
||||
>id : ((s: string) => string) | ((arg: string) => number)
|
||||
>id : (s: string) => string
|
||||
>arg => arg.length : (arg: string) => number
|
||||
>arg : string
|
||||
>arg.length : number
|
||||
@ -80,7 +80,7 @@ interface Tuples {
|
||||
}
|
||||
function g({ prop = [101, 1234] }: Tuples) {}
|
||||
>g : ({ prop }: Tuples) => void
|
||||
>prop : [string, number] | [number, number]
|
||||
>prop : [string, number]
|
||||
>[101, 1234] : [number, number]
|
||||
>101 : 101
|
||||
>1234 : 1234
|
||||
@ -94,7 +94,7 @@ interface StringUnion {
|
||||
}
|
||||
function h({ prop = "baz" }: StringUnion) {}
|
||||
>h : ({ prop }: StringUnion) => void
|
||||
>prop : "foo" | "bar" | "baz"
|
||||
>prop : "foo" | "bar"
|
||||
>"baz" : "baz"
|
||||
>StringUnion : StringUnion
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts(4,5): error TS2322: Type '"z"' is not assignable to type '"x" | "y"'.
|
||||
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts(5,15): error TS2322: Type '"c"' is not assignable to type '"a" | "b"'.
|
||||
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts(17,6): error TS2345: Argument of type '{ method: "z"; nested: { p: "b"; }; }' is not assignable to parameter of type '{ method?: "x" | "y"; nested?: { p: "a" | "b"; }; }'.
|
||||
Types of property 'method' are incompatible.
|
||||
Type '"z"' is not assignable to type '"x" | "y"'.
|
||||
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts(18,6): error TS2345: Argument of type '{ method: "one"; nested: { p: "a"; }; }' is not assignable to parameter of type '{ method?: "x" | "y"; nested?: { p: "a" | "b"; }; }'.
|
||||
Types of property 'method' are incompatible.
|
||||
Type '"one"' is not assignable to type '"x" | "y"'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts (4 errors) ====
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test({
|
||||
method = 'z',
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '"z"' is not assignable to type '"x" | "y"'.
|
||||
nested: { p = 'c' }
|
||||
~
|
||||
!!! error TS2322: Type '"c"' is not assignable to type '"a" | "b"'.
|
||||
}: {
|
||||
method?: 'x' | 'y',
|
||||
nested?: { p: 'a' | 'b' }
|
||||
})
|
||||
{
|
||||
method
|
||||
p
|
||||
}
|
||||
|
||||
test({});
|
||||
test({ method: 'x', nested: { p: 'a' } })
|
||||
test({ method: 'z', nested: { p: 'b' } })
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ method: "z"; nested: { p: "b"; }; }' is not assignable to parameter of type '{ method?: "x" | "y"; nested?: { p: "a" | "b"; }; }'.
|
||||
!!! error TS2345: Types of property 'method' are incompatible.
|
||||
!!! error TS2345: Type '"z"' is not assignable to type '"x" | "y"'.
|
||||
test({ method: 'one', nested: { p: 'a' } })
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ method: "one"; nested: { p: "a"; }; }' is not assignable to parameter of type '{ method?: "x" | "y"; nested?: { p: "a" | "b"; }; }'.
|
||||
!!! error TS2345: Types of property 'method' are incompatible.
|
||||
!!! error TS2345: Type '"one"' is not assignable to type '"x" | "y"'.
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
//// [destructuringParameterDeclaration8.ts]
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test({
|
||||
method = 'z',
|
||||
nested: { p = 'c' }
|
||||
}: {
|
||||
method?: 'x' | 'y',
|
||||
nested?: { p: 'a' | 'b' }
|
||||
})
|
||||
{
|
||||
method
|
||||
p
|
||||
}
|
||||
|
||||
test({});
|
||||
test({ method: 'x', nested: { p: 'a' } })
|
||||
test({ method: 'z', nested: { p: 'b' } })
|
||||
test({ method: 'one', nested: { p: 'a' } })
|
||||
|
||||
|
||||
//// [destructuringParameterDeclaration8.js]
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test(_a) {
|
||||
var _b = _a.method, method = _b === void 0 ? 'z' : _b, _c = _a.nested.p, p = _c === void 0 ? 'c' : _c;
|
||||
method;
|
||||
p;
|
||||
}
|
||||
test({});
|
||||
test({ method: 'x', nested: { p: 'a' } });
|
||||
test({ method: 'z', nested: { p: 'b' } });
|
||||
test({ method: 'one', nested: { p: 'a' } });
|
||||
@ -0,0 +1,51 @@
|
||||
=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts ===
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test({
|
||||
>test : Symbol(test, Decl(destructuringParameterDeclaration8.ts, 0, 0))
|
||||
|
||||
method = 'z',
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 2, 15))
|
||||
|
||||
nested: { p = 'c' }
|
||||
>nested : Symbol(nested, Decl(destructuringParameterDeclaration8.ts, 6, 23))
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 4, 13))
|
||||
|
||||
}: {
|
||||
method?: 'x' | 'y',
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 5, 4))
|
||||
|
||||
nested?: { p: 'a' | 'b' }
|
||||
>nested : Symbol(nested, Decl(destructuringParameterDeclaration8.ts, 6, 23))
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 7, 14))
|
||||
|
||||
})
|
||||
{
|
||||
method
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 2, 15))
|
||||
|
||||
p
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 4, 13))
|
||||
}
|
||||
|
||||
test({});
|
||||
>test : Symbol(test, Decl(destructuringParameterDeclaration8.ts, 0, 0))
|
||||
|
||||
test({ method: 'x', nested: { p: 'a' } })
|
||||
>test : Symbol(test, Decl(destructuringParameterDeclaration8.ts, 0, 0))
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 15, 6))
|
||||
>nested : Symbol(nested, Decl(destructuringParameterDeclaration8.ts, 15, 19))
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 15, 29))
|
||||
|
||||
test({ method: 'z', nested: { p: 'b' } })
|
||||
>test : Symbol(test, Decl(destructuringParameterDeclaration8.ts, 0, 0))
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 16, 6))
|
||||
>nested : Symbol(nested, Decl(destructuringParameterDeclaration8.ts, 16, 19))
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 16, 29))
|
||||
|
||||
test({ method: 'one', nested: { p: 'a' } })
|
||||
>test : Symbol(test, Decl(destructuringParameterDeclaration8.ts, 0, 0))
|
||||
>method : Symbol(method, Decl(destructuringParameterDeclaration8.ts, 17, 6))
|
||||
>nested : Symbol(nested, Decl(destructuringParameterDeclaration8.ts, 17, 21))
|
||||
>p : Symbol(p, Decl(destructuringParameterDeclaration8.ts, 17, 31))
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8.ts ===
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test({
|
||||
>test : ({ method, nested: { p } }: { method?: "x" | "y"; nested?: { p: "a" | "b"; }; }) => void
|
||||
|
||||
method = 'z',
|
||||
>method : "x" | "y"
|
||||
>'z' : "z"
|
||||
|
||||
nested: { p = 'c' }
|
||||
>nested : any
|
||||
>p : "a" | "b"
|
||||
>'c' : "c"
|
||||
|
||||
}: {
|
||||
method?: 'x' | 'y',
|
||||
>method : "x" | "y"
|
||||
|
||||
nested?: { p: 'a' | 'b' }
|
||||
>nested : { p: "a" | "b"; }
|
||||
>p : "a" | "b"
|
||||
|
||||
})
|
||||
{
|
||||
method
|
||||
>method : "x" | "y"
|
||||
|
||||
p
|
||||
>p : "a" | "b"
|
||||
}
|
||||
|
||||
test({});
|
||||
>test({}) : void
|
||||
>test : ({ method, nested: { p } }: { method?: "x" | "y"; nested?: { p: "a" | "b"; }; }) => void
|
||||
>{} : {}
|
||||
|
||||
test({ method: 'x', nested: { p: 'a' } })
|
||||
>test({ method: 'x', nested: { p: 'a' } }) : void
|
||||
>test : ({ method, nested: { p } }: { method?: "x" | "y"; nested?: { p: "a" | "b"; }; }) => void
|
||||
>{ method: 'x', nested: { p: 'a' } } : { method: "x"; nested: { p: "a"; }; }
|
||||
>method : "x"
|
||||
>'x' : "x"
|
||||
>nested : { p: "a"; }
|
||||
>{ p: 'a' } : { p: "a"; }
|
||||
>p : "a"
|
||||
>'a' : "a"
|
||||
|
||||
test({ method: 'z', nested: { p: 'b' } })
|
||||
>test({ method: 'z', nested: { p: 'b' } }) : void
|
||||
>test : ({ method, nested: { p } }: { method?: "x" | "y"; nested?: { p: "a" | "b"; }; }) => void
|
||||
>{ method: 'z', nested: { p: 'b' } } : { method: string; nested: { p: string; }; }
|
||||
>method : string
|
||||
>'z' : "z"
|
||||
>nested : { p: string; }
|
||||
>{ p: 'b' } : { p: string; }
|
||||
>p : string
|
||||
>'b' : "b"
|
||||
|
||||
test({ method: 'one', nested: { p: 'a' } })
|
||||
>test({ method: 'one', nested: { p: 'a' } }) : void
|
||||
>test : ({ method, nested: { p } }: { method?: "x" | "y"; nested?: { p: "a" | "b"; }; }) => void
|
||||
>{ method: 'one', nested: { p: 'a' } } : { method: string; nested: { p: string; }; }
|
||||
>method : string
|
||||
>'one' : "one"
|
||||
>nested : { p: string; }
|
||||
>{ p: 'a' } : { p: string; }
|
||||
>p : string
|
||||
>'a' : "a"
|
||||
|
||||
@ -5,9 +5,11 @@ tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(4
|
||||
Type '[[boolean]]' is not assignable to type '[[string]]'.
|
||||
Type '[boolean]' is not assignable to type '[string]'.
|
||||
Type 'boolean' is not assignable to type 'string'.
|
||||
tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(19,10): error TS2322: Type 'string[]' is not assignable to type 'number[]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts (2 errors) ====
|
||||
==== tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts (3 errors) ====
|
||||
// The type T associated with a destructuring variable declaration is determined as follows:
|
||||
// If the declaration includes a type annotation, T is that type.
|
||||
var {a1, a2}: { a1: number, a2: string } = { a1: true, a2: 1 } // Error
|
||||
@ -35,4 +37,7 @@ tests/cases/conformance/es6/destructuring/destructuringVariableDeclaration2.ts(4
|
||||
// When a destructuring variable declaration, binding property, or binding element specifies
|
||||
// an initializer expression, the type of the initializer expression is required to be assignable
|
||||
// to the widened form of the type associated with the destructuring variable declaration, binding property, or binding element.
|
||||
var {d: {d1 = ["string", null]}}: { d: { d1: number[] } } = { d: { d1: [1, 2] } }; // Error
|
||||
var {d: {d1 = ["string", null]}}: { d: { d1: number[] } } = { d: { d1: [1, 2] } }; // Error
|
||||
~~
|
||||
!!! error TS2322: Type 'string[]' is not assignable to type 'number[]'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
@ -74,7 +74,7 @@ var [c1, c2, { c3: c4, c5 }, , ...c6] = [1, 2, { c3: 4, c5: 0 }]; // Error
|
||||
// to the widened form of the type associated with the destructuring variable declaration, binding property, or binding element.
|
||||
var {d: {d1 = ["string", null]}}: { d: { d1: number[] } } = { d: { d1: [1, 2] } }; // Error
|
||||
>d : any
|
||||
>d1 : string[] | number[]
|
||||
>d1 : number[]
|
||||
>["string", null] : string[]
|
||||
>"string" : "string"
|
||||
>null : null
|
||||
|
||||
@ -8,8 +8,7 @@ tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(31,8): e
|
||||
Type 'undefined' is not assignable to type 'number'.
|
||||
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(45,10): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
|
||||
Type 'undefined' is not assignable to type 'number'.
|
||||
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(53,11): error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number | undefined'.
|
||||
Type 'null' is not assignable to type 'number | undefined'.
|
||||
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(52,24): error TS2322: Type 'null' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts (6 errors) ====
|
||||
@ -80,10 +79,9 @@ tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(53,11):
|
||||
performFoo();
|
||||
|
||||
function performFoo2({ bar = null }: Foo = {}) {
|
||||
~~~
|
||||
!!! error TS2322: Type 'null' is not assignable to type 'number'.
|
||||
useBar2(bar);
|
||||
~~~
|
||||
!!! error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number | undefined'.
|
||||
!!! error TS2345: Type 'null' is not assignable to type 'number | undefined'.
|
||||
}
|
||||
|
||||
declare function useBar2(bar: number | undefined): void;
|
||||
|
||||
@ -225,7 +225,7 @@ performFoo();
|
||||
|
||||
function performFoo2({ bar = null }: Foo = {}) {
|
||||
>performFoo2 : ({ bar }?: Foo) => void
|
||||
>bar : number | null
|
||||
>bar : number
|
||||
>null : null
|
||||
>Foo : Foo
|
||||
>{} : {}
|
||||
@ -233,7 +233,7 @@ function performFoo2({ bar = null }: Foo = {}) {
|
||||
useBar2(bar);
|
||||
>useBar2(bar) : void
|
||||
>useBar2 : (bar: number | undefined) => void
|
||||
>bar : number | null
|
||||
>bar : number
|
||||
}
|
||||
|
||||
declare function useBar2(bar: number | undefined): void;
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
// explicit type annotation should cause `method` to have type 'x' | 'y'
|
||||
// both inside and outside `test`.
|
||||
function test({
|
||||
method = 'z',
|
||||
nested: { p = 'c' }
|
||||
}: {
|
||||
method?: 'x' | 'y',
|
||||
nested?: { p: 'a' | 'b' }
|
||||
})
|
||||
{
|
||||
method
|
||||
p
|
||||
}
|
||||
|
||||
test({});
|
||||
test({ method: 'x', nested: { p: 'a' } })
|
||||
test({ method: 'z', nested: { p: 'b' } })
|
||||
test({ method: 'one', nested: { p: 'a' } })
|
||||
@ -1 +1 @@
|
||||
Subproject commit 40bdb4eadabc9fbed7d83e3f26817a931c0763b6
|
||||
Subproject commit 6b9706810b55af326a93b9aa59cb17815a30bb32
|
||||
Loading…
x
Reference in New Issue
Block a user