Make no inferences from binding patterns with no defaults (#35454)
* Use nonInferrableAnyType in types inferred from binding patterns * Add regression tests * Accept new baselines
This commit is contained in:
parent
b39b4e05be
commit
09271f107d
|
@ -638,6 +638,7 @@ namespace ts {
|
|||
const autoType = createIntrinsicType(TypeFlags.Any, "any");
|
||||
const wildcardType = createIntrinsicType(TypeFlags.Any, "any");
|
||||
const errorType = createIntrinsicType(TypeFlags.Any, "error");
|
||||
const nonInferrableAnyType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.ContainsWideningType);
|
||||
const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
|
||||
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
|
||||
|
@ -7156,7 +7157,11 @@ namespace ts {
|
|||
if (reportErrors && !declarationBelongsToPrivateAmbientMember(element)) {
|
||||
reportImplicitAny(element, anyType);
|
||||
}
|
||||
return anyType;
|
||||
// When we're including the pattern in the type (an indication we're obtaining a contextual type), we
|
||||
// use the non-inferrable any type. Inference will never directly infer this type, but it is possible
|
||||
// to infer a type that contains it, e.g. for a binding pattern like [foo] or { foo }. In such cases,
|
||||
// widening of the binding pattern type substitutes a regular any for the non-inferrable any.
|
||||
return includePatternInType ? nonInferrableAnyType : anyType;
|
||||
}
|
||||
|
||||
// Return the type implied by an object binding pattern
|
||||
|
@ -7188,6 +7193,7 @@ namespace ts {
|
|||
result.objectFlags |= objectFlags;
|
||||
if (includePatternInType) {
|
||||
result.pattern = pattern;
|
||||
result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -7206,6 +7212,7 @@ namespace ts {
|
|||
if (includePatternInType) {
|
||||
result = cloneTypeReference(result);
|
||||
result.pattern = pattern;
|
||||
result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -17025,7 +17032,7 @@ namespace ts {
|
|||
return type.widened;
|
||||
}
|
||||
let result: Type | undefined;
|
||||
if (type.flags & TypeFlags.Nullable) {
|
||||
if (type.flags & (TypeFlags.Any | TypeFlags.Nullable)) {
|
||||
result = anyType;
|
||||
}
|
||||
else if (isObjectLiteralType(type)) {
|
||||
|
@ -17535,7 +17542,8 @@ namespace ts {
|
|||
// not contain anyFunctionType when we come back to this argument for its second round
|
||||
// of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard
|
||||
// when constructing types from type parameters that had no inference candidates).
|
||||
if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
|
||||
if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableAnyType || source === silentNeverType ||
|
||||
(priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
|
||||
return;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
|
|
|
@ -4232,7 +4232,7 @@ namespace ts {
|
|||
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
|
||||
StructuredOrInstantiable = StructuredType | Instantiable,
|
||||
/* @internal */
|
||||
ObjectFlagsType = Nullable | Never | Object | Union | Intersection,
|
||||
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection,
|
||||
/* @internal */
|
||||
Simplifiable = IndexedAccess | Conditional,
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
|
|
61
tests/baselines/reference/inferFromBindingPattern.js
Normal file
61
tests/baselines/reference/inferFromBindingPattern.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
//// [inferFromBindingPattern.ts]
|
||||
declare function f1<T extends string>(): T;
|
||||
declare function f2<T extends string>(): [T];
|
||||
declare function f3<T extends string>(): { x: T };
|
||||
|
||||
let x1 = f1(); // string
|
||||
let [x2] = f2(); // string
|
||||
let { x: x3 } = f3(); // string
|
||||
|
||||
// Repro from #30379
|
||||
|
||||
function foo<T = number>(): [T] {
|
||||
return [42 as any]
|
||||
}
|
||||
const [x] = foo(); // [number]
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
interface SelectProps<T, K> {
|
||||
selector?: (obj: T) => K;
|
||||
}
|
||||
|
||||
type SelectResult<T, K> = [K, T];
|
||||
|
||||
interface Person {
|
||||
name: string;
|
||||
surname: string;
|
||||
}
|
||||
|
||||
declare function selectJohn<K = Person>(props?: SelectProps<Person, K>): SelectResult<Person, K>;
|
||||
|
||||
const [person] = selectJohn();
|
||||
const [any, whatever] = selectJohn();
|
||||
const john = selectJohn();
|
||||
const [personAgain, nufinspecial] = john;
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
declare function makeTuple<T1>(arg: T1): [T1];
|
||||
declare function stringy<T = string>(arg?: T): T;
|
||||
|
||||
const isStringTuple = makeTuple(stringy()); // [string]
|
||||
const [isAny] = makeTuple(stringy()); // [string]
|
||||
|
||||
|
||||
//// [inferFromBindingPattern.js]
|
||||
"use strict";
|
||||
var x1 = f1(); // string
|
||||
var x2 = f2()[0]; // string
|
||||
var x3 = f3().x; // string
|
||||
// Repro from #30379
|
||||
function foo() {
|
||||
return [42];
|
||||
}
|
||||
var x = foo()[0]; // [number]
|
||||
var person = selectJohn()[0];
|
||||
var _a = selectJohn(), any = _a[0], whatever = _a[1];
|
||||
var john = selectJohn();
|
||||
var personAgain = john[0], nufinspecial = john[1];
|
||||
var isStringTuple = makeTuple(stringy()); // [string]
|
||||
var isAny = makeTuple(stringy())[0]; // [string]
|
130
tests/baselines/reference/inferFromBindingPattern.symbols
Normal file
130
tests/baselines/reference/inferFromBindingPattern.symbols
Normal file
|
@ -0,0 +1,130 @@
|
|||
=== tests/cases/conformance/inferFromBindingPattern.ts ===
|
||||
declare function f1<T extends string>(): T;
|
||||
>f1 : Symbol(f1, Decl(inferFromBindingPattern.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 0, 20))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 0, 20))
|
||||
|
||||
declare function f2<T extends string>(): [T];
|
||||
>f2 : Symbol(f2, Decl(inferFromBindingPattern.ts, 0, 43))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 1, 20))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 1, 20))
|
||||
|
||||
declare function f3<T extends string>(): { x: T };
|
||||
>f3 : Symbol(f3, Decl(inferFromBindingPattern.ts, 1, 45))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 2, 20))
|
||||
>x : Symbol(x, Decl(inferFromBindingPattern.ts, 2, 42))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 2, 20))
|
||||
|
||||
let x1 = f1(); // string
|
||||
>x1 : Symbol(x1, Decl(inferFromBindingPattern.ts, 4, 3))
|
||||
>f1 : Symbol(f1, Decl(inferFromBindingPattern.ts, 0, 0))
|
||||
|
||||
let [x2] = f2(); // string
|
||||
>x2 : Symbol(x2, Decl(inferFromBindingPattern.ts, 5, 5))
|
||||
>f2 : Symbol(f2, Decl(inferFromBindingPattern.ts, 0, 43))
|
||||
|
||||
let { x: x3 } = f3(); // string
|
||||
>x : Symbol(x, Decl(inferFromBindingPattern.ts, 2, 42))
|
||||
>x3 : Symbol(x3, Decl(inferFromBindingPattern.ts, 6, 5))
|
||||
>f3 : Symbol(f3, Decl(inferFromBindingPattern.ts, 1, 45))
|
||||
|
||||
// Repro from #30379
|
||||
|
||||
function foo<T = number>(): [T] {
|
||||
>foo : Symbol(foo, Decl(inferFromBindingPattern.ts, 6, 21))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 10, 13))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 10, 13))
|
||||
|
||||
return [42 as any]
|
||||
}
|
||||
const [x] = foo(); // [number]
|
||||
>x : Symbol(x, Decl(inferFromBindingPattern.ts, 13, 7))
|
||||
>foo : Symbol(foo, Decl(inferFromBindingPattern.ts, 6, 21))
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
interface SelectProps<T, K> {
|
||||
>SelectProps : Symbol(SelectProps, Decl(inferFromBindingPattern.ts, 13, 18))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 17, 22))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 17, 24))
|
||||
|
||||
selector?: (obj: T) => K;
|
||||
>selector : Symbol(SelectProps.selector, Decl(inferFromBindingPattern.ts, 17, 29))
|
||||
>obj : Symbol(obj, Decl(inferFromBindingPattern.ts, 18, 14))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 17, 22))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 17, 24))
|
||||
}
|
||||
|
||||
type SelectResult<T, K> = [K, T];
|
||||
>SelectResult : Symbol(SelectResult, Decl(inferFromBindingPattern.ts, 19, 1))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 21, 18))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 21, 20))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 21, 20))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 21, 18))
|
||||
|
||||
interface Person {
|
||||
>Person : Symbol(Person, Decl(inferFromBindingPattern.ts, 21, 33))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(Person.name, Decl(inferFromBindingPattern.ts, 23, 18))
|
||||
|
||||
surname: string;
|
||||
>surname : Symbol(Person.surname, Decl(inferFromBindingPattern.ts, 24, 15))
|
||||
}
|
||||
|
||||
declare function selectJohn<K = Person>(props?: SelectProps<Person, K>): SelectResult<Person, K>;
|
||||
>selectJohn : Symbol(selectJohn, Decl(inferFromBindingPattern.ts, 26, 1))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 28, 28))
|
||||
>Person : Symbol(Person, Decl(inferFromBindingPattern.ts, 21, 33))
|
||||
>props : Symbol(props, Decl(inferFromBindingPattern.ts, 28, 40))
|
||||
>SelectProps : Symbol(SelectProps, Decl(inferFromBindingPattern.ts, 13, 18))
|
||||
>Person : Symbol(Person, Decl(inferFromBindingPattern.ts, 21, 33))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 28, 28))
|
||||
>SelectResult : Symbol(SelectResult, Decl(inferFromBindingPattern.ts, 19, 1))
|
||||
>Person : Symbol(Person, Decl(inferFromBindingPattern.ts, 21, 33))
|
||||
>K : Symbol(K, Decl(inferFromBindingPattern.ts, 28, 28))
|
||||
|
||||
const [person] = selectJohn();
|
||||
>person : Symbol(person, Decl(inferFromBindingPattern.ts, 30, 7))
|
||||
>selectJohn : Symbol(selectJohn, Decl(inferFromBindingPattern.ts, 26, 1))
|
||||
|
||||
const [any, whatever] = selectJohn();
|
||||
>any : Symbol(any, Decl(inferFromBindingPattern.ts, 31, 7))
|
||||
>whatever : Symbol(whatever, Decl(inferFromBindingPattern.ts, 31, 11))
|
||||
>selectJohn : Symbol(selectJohn, Decl(inferFromBindingPattern.ts, 26, 1))
|
||||
|
||||
const john = selectJohn();
|
||||
>john : Symbol(john, Decl(inferFromBindingPattern.ts, 32, 5))
|
||||
>selectJohn : Symbol(selectJohn, Decl(inferFromBindingPattern.ts, 26, 1))
|
||||
|
||||
const [personAgain, nufinspecial] = john;
|
||||
>personAgain : Symbol(personAgain, Decl(inferFromBindingPattern.ts, 33, 7))
|
||||
>nufinspecial : Symbol(nufinspecial, Decl(inferFromBindingPattern.ts, 33, 19))
|
||||
>john : Symbol(john, Decl(inferFromBindingPattern.ts, 32, 5))
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
declare function makeTuple<T1>(arg: T1): [T1];
|
||||
>makeTuple : Symbol(makeTuple, Decl(inferFromBindingPattern.ts, 33, 41))
|
||||
>T1 : Symbol(T1, Decl(inferFromBindingPattern.ts, 37, 27))
|
||||
>arg : Symbol(arg, Decl(inferFromBindingPattern.ts, 37, 31))
|
||||
>T1 : Symbol(T1, Decl(inferFromBindingPattern.ts, 37, 27))
|
||||
>T1 : Symbol(T1, Decl(inferFromBindingPattern.ts, 37, 27))
|
||||
|
||||
declare function stringy<T = string>(arg?: T): T;
|
||||
>stringy : Symbol(stringy, Decl(inferFromBindingPattern.ts, 37, 46))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 38, 25))
|
||||
>arg : Symbol(arg, Decl(inferFromBindingPattern.ts, 38, 37))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 38, 25))
|
||||
>T : Symbol(T, Decl(inferFromBindingPattern.ts, 38, 25))
|
||||
|
||||
const isStringTuple = makeTuple(stringy()); // [string]
|
||||
>isStringTuple : Symbol(isStringTuple, Decl(inferFromBindingPattern.ts, 40, 5))
|
||||
>makeTuple : Symbol(makeTuple, Decl(inferFromBindingPattern.ts, 33, 41))
|
||||
>stringy : Symbol(stringy, Decl(inferFromBindingPattern.ts, 37, 46))
|
||||
|
||||
const [isAny] = makeTuple(stringy()); // [string]
|
||||
>isAny : Symbol(isAny, Decl(inferFromBindingPattern.ts, 41, 7))
|
||||
>makeTuple : Symbol(makeTuple, Decl(inferFromBindingPattern.ts, 33, 41))
|
||||
>stringy : Symbol(stringy, Decl(inferFromBindingPattern.ts, 37, 46))
|
||||
|
110
tests/baselines/reference/inferFromBindingPattern.types
Normal file
110
tests/baselines/reference/inferFromBindingPattern.types
Normal file
|
@ -0,0 +1,110 @@
|
|||
=== tests/cases/conformance/inferFromBindingPattern.ts ===
|
||||
declare function f1<T extends string>(): T;
|
||||
>f1 : <T extends string>() => T
|
||||
|
||||
declare function f2<T extends string>(): [T];
|
||||
>f2 : <T extends string>() => [T]
|
||||
|
||||
declare function f3<T extends string>(): { x: T };
|
||||
>f3 : <T extends string>() => { x: T; }
|
||||
>x : T
|
||||
|
||||
let x1 = f1(); // string
|
||||
>x1 : string
|
||||
>f1() : string
|
||||
>f1 : <T extends string>() => T
|
||||
|
||||
let [x2] = f2(); // string
|
||||
>x2 : string
|
||||
>f2() : [string]
|
||||
>f2 : <T extends string>() => [T]
|
||||
|
||||
let { x: x3 } = f3(); // string
|
||||
>x : any
|
||||
>x3 : string
|
||||
>f3() : { x: string; }
|
||||
>f3 : <T extends string>() => { x: T; }
|
||||
|
||||
// Repro from #30379
|
||||
|
||||
function foo<T = number>(): [T] {
|
||||
>foo : <T = number>() => [T]
|
||||
|
||||
return [42 as any]
|
||||
>[42 as any] : [any]
|
||||
>42 as any : any
|
||||
>42 : 42
|
||||
}
|
||||
const [x] = foo(); // [number]
|
||||
>x : number
|
||||
>foo() : [number]
|
||||
>foo : <T = number>() => [T]
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
interface SelectProps<T, K> {
|
||||
selector?: (obj: T) => K;
|
||||
>selector : ((obj: T) => K) | undefined
|
||||
>obj : T
|
||||
}
|
||||
|
||||
type SelectResult<T, K> = [K, T];
|
||||
>SelectResult : SelectResult<T, K>
|
||||
|
||||
interface Person {
|
||||
name: string;
|
||||
>name : string
|
||||
|
||||
surname: string;
|
||||
>surname : string
|
||||
}
|
||||
|
||||
declare function selectJohn<K = Person>(props?: SelectProps<Person, K>): SelectResult<Person, K>;
|
||||
>selectJohn : <K = Person>(props?: SelectProps<Person, K> | undefined) => SelectResult<Person, K>
|
||||
>props : SelectProps<Person, K> | undefined
|
||||
|
||||
const [person] = selectJohn();
|
||||
>person : Person
|
||||
>selectJohn() : SelectResult<Person, Person>
|
||||
>selectJohn : <K = Person>(props?: SelectProps<Person, K> | undefined) => SelectResult<Person, K>
|
||||
|
||||
const [any, whatever] = selectJohn();
|
||||
>any : Person
|
||||
>whatever : Person
|
||||
>selectJohn() : SelectResult<Person, Person>
|
||||
>selectJohn : <K = Person>(props?: SelectProps<Person, K> | undefined) => SelectResult<Person, K>
|
||||
|
||||
const john = selectJohn();
|
||||
>john : SelectResult<Person, Person>
|
||||
>selectJohn() : SelectResult<Person, Person>
|
||||
>selectJohn : <K = Person>(props?: SelectProps<Person, K> | undefined) => SelectResult<Person, K>
|
||||
|
||||
const [personAgain, nufinspecial] = john;
|
||||
>personAgain : Person
|
||||
>nufinspecial : Person
|
||||
>john : SelectResult<Person, Person>
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
declare function makeTuple<T1>(arg: T1): [T1];
|
||||
>makeTuple : <T1>(arg: T1) => [T1]
|
||||
>arg : T1
|
||||
|
||||
declare function stringy<T = string>(arg?: T): T;
|
||||
>stringy : <T = string>(arg?: T | undefined) => T
|
||||
>arg : T | undefined
|
||||
|
||||
const isStringTuple = makeTuple(stringy()); // [string]
|
||||
>isStringTuple : [string]
|
||||
>makeTuple(stringy()) : [string]
|
||||
>makeTuple : <T1>(arg: T1) => [T1]
|
||||
>stringy() : string
|
||||
>stringy : <T = string>(arg?: T | undefined) => T
|
||||
|
||||
const [isAny] = makeTuple(stringy()); // [string]
|
||||
>isAny : string
|
||||
>makeTuple(stringy()) : [string]
|
||||
>makeTuple : <T1>(arg: T1) => [T1]
|
||||
>stringy() : string
|
||||
>stringy : <T = string>(arg?: T | undefined) => T
|
||||
|
44
tests/cases/conformance/inferFromBindingPattern.ts
Normal file
44
tests/cases/conformance/inferFromBindingPattern.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
// @strict: true
|
||||
|
||||
declare function f1<T extends string>(): T;
|
||||
declare function f2<T extends string>(): [T];
|
||||
declare function f3<T extends string>(): { x: T };
|
||||
|
||||
let x1 = f1(); // string
|
||||
let [x2] = f2(); // string
|
||||
let { x: x3 } = f3(); // string
|
||||
|
||||
// Repro from #30379
|
||||
|
||||
function foo<T = number>(): [T] {
|
||||
return [42 as any]
|
||||
}
|
||||
const [x] = foo(); // [number]
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
interface SelectProps<T, K> {
|
||||
selector?: (obj: T) => K;
|
||||
}
|
||||
|
||||
type SelectResult<T, K> = [K, T];
|
||||
|
||||
interface Person {
|
||||
name: string;
|
||||
surname: string;
|
||||
}
|
||||
|
||||
declare function selectJohn<K = Person>(props?: SelectProps<Person, K>): SelectResult<Person, K>;
|
||||
|
||||
const [person] = selectJohn();
|
||||
const [any, whatever] = selectJohn();
|
||||
const john = selectJohn();
|
||||
const [personAgain, nufinspecial] = john;
|
||||
|
||||
// Repro from #35291
|
||||
|
||||
declare function makeTuple<T1>(arg: T1): [T1];
|
||||
declare function stringy<T = string>(arg?: T): T;
|
||||
|
||||
const isStringTuple = makeTuple(stringy()); // [string]
|
||||
const [isAny] = makeTuple(stringy()); // [string]
|
Loading…
Reference in a new issue