Merge pull request #32969 from collin5/b30851-2

Restrict spreading for unknown Type with non object constraint
This commit is contained in:
Orta
2019-08-19 08:43:11 -07:00
committed by GitHub
6 changed files with 62 additions and 40 deletions
+1 -1
View File
@@ -19878,7 +19878,7 @@ namespace ts {
return isValidSpreadType(constraint);
}
}
return !!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
return !!(type.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
getFalsyFlags(type) & TypeFlags.DefinitelyFalsy && isValidSpreadType(removeDefinitelyFalsyTypes(type)) ||
type.flags & TypeFlags.UnionOrIntersection && every((<UnionOrIntersectionType>type).types, isValidSpreadType));
}
@@ -21,16 +21,18 @@ tests/cases/conformance/types/unknown/unknownType1.ts(120,9): error TS2322: Type
tests/cases/conformance/types/unknown/unknownType1.ts(128,5): error TS2322: Type 'number[]' is not assignable to type '{ [x: string]: unknown; }'.
Index signature is missing in type 'number[]'.
tests/cases/conformance/types/unknown/unknownType1.ts(129,5): error TS2322: Type '123' is not assignable to type '{ [x: string]: unknown; }'.
tests/cases/conformance/types/unknown/unknownType1.ts(149,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/conformance/types/unknown/unknownType1.ts(155,14): error TS2700: Rest types may only be created from object types.
tests/cases/conformance/types/unknown/unknownType1.ts(161,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/types/unknown/unknownType1.ts(170,9): error TS2322: Type 'U' is not assignable to type '{}'.
tests/cases/conformance/types/unknown/unknownType1.ts(143,29): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/unknown/unknownType1.ts(144,29): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/unknown/unknownType1.ts(150,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/conformance/types/unknown/unknownType1.ts(156,14): error TS2700: Rest types may only be created from object types.
tests/cases/conformance/types/unknown/unknownType1.ts(162,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/types/unknown/unknownType1.ts(171,9): error TS2322: Type 'U' is not assignable to type '{}'.
Type 'unknown' is not assignable to type '{}'.
tests/cases/conformance/types/unknown/unknownType1.ts(180,5): error TS2322: Type 'T' is not assignable to type '{}'.
tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type 'T' is not assignable to type '{}'.
Type 'unknown' is not assignable to type '{}'.
==== tests/cases/conformance/types/unknown/unknownType1.ts (25 errors) ====
==== tests/cases/conformance/types/unknown/unknownType1.ts (27 errors) ====
// In an intersection everything absorbs unknown
type T00 = unknown & null; // null
@@ -217,7 +219,12 @@ tests/cases/conformance/types/unknown/unknownType1.ts(180,5): error TS2322: Type
function f26(x: {}, y: unknown, z: any) {
let o1 = { a: 42, ...x }; // { a: number }
let o2 = { a: 42, ...x, ...y }; // unknown
~~~~
!!! error TS2698: Spread types may only be created from object types.
let o3 = { a: 42, ...x, ...y, ...z }; // any
~~~~
!!! error TS2698: Spread types may only be created from object types.
let o4 = { a: 42, ...z }; // any
}
// Functions with unknown return type don't need return expressions
@@ -143,6 +143,7 @@ function f26(x: {}, y: unknown, z: any) {
let o1 = { a: 42, ...x }; // { a: number }
let o2 = { a: 42, ...x, ...y }; // unknown
let o3 = { a: 42, ...x, ...y, ...z }; // any
let o4 = { a: 42, ...z }; // any
}
// Functions with unknown return type don't need return expressions
@@ -281,6 +282,7 @@ function f26(x, y, z) {
var o1 = __assign({ a: 42 }, x); // { a: number }
var o2 = __assign(__assign({ a: 42 }, x), y); // unknown
var o3 = __assign(__assign(__assign({ a: 42 }, x), y), z); // any
var o4 = __assign({ a: 42 }, z); // any
}
// Functions with unknown return type don't need return expressions
function f27() {
+36 -31
View File
@@ -372,82 +372,87 @@ function f26(x: {}, y: unknown, z: any) {
>a : Symbol(a, Decl(unknownType1.ts, 143, 14))
>x : Symbol(x, Decl(unknownType1.ts, 140, 13))
>y : Symbol(y, Decl(unknownType1.ts, 140, 19))
>z : Symbol(z, Decl(unknownType1.ts, 140, 31))
let o4 = { a: 42, ...z }; // any
>o4 : Symbol(o4, Decl(unknownType1.ts, 144, 7))
>a : Symbol(a, Decl(unknownType1.ts, 144, 14))
>z : Symbol(z, Decl(unknownType1.ts, 140, 31))
}
// Functions with unknown return type don't need return expressions
function f27(): unknown {
>f27 : Symbol(f27, Decl(unknownType1.ts, 144, 1))
>f27 : Symbol(f27, Decl(unknownType1.ts, 145, 1))
}
// Rest type cannot be created from unknown
function f28(x: unknown) {
>f28 : Symbol(f28, Decl(unknownType1.ts, 149, 1))
>x : Symbol(x, Decl(unknownType1.ts, 153, 13))
>f28 : Symbol(f28, Decl(unknownType1.ts, 150, 1))
>x : Symbol(x, Decl(unknownType1.ts, 154, 13))
let { ...a } = x; // Error
>a : Symbol(a, Decl(unknownType1.ts, 154, 9))
>x : Symbol(x, Decl(unknownType1.ts, 153, 13))
>a : Symbol(a, Decl(unknownType1.ts, 155, 9))
>x : Symbol(x, Decl(unknownType1.ts, 154, 13))
}
// Class properties of type unknown don't need definite assignment
class C1 {
>C1 : Symbol(C1, Decl(unknownType1.ts, 155, 1))
>C1 : Symbol(C1, Decl(unknownType1.ts, 156, 1))
a: string; // Error
>a : Symbol(C1.a, Decl(unknownType1.ts, 159, 10))
>a : Symbol(C1.a, Decl(unknownType1.ts, 160, 10))
b: unknown;
>b : Symbol(C1.b, Decl(unknownType1.ts, 160, 14))
>b : Symbol(C1.b, Decl(unknownType1.ts, 161, 14))
c: any;
>c : Symbol(C1.c, Decl(unknownType1.ts, 161, 15))
>c : Symbol(C1.c, Decl(unknownType1.ts, 162, 15))
}
// Type parameter with explicit 'unknown' constraint not assignable to '{}'
function f30<T, U extends unknown>(t: T, u: U) {
>f30 : Symbol(f30, Decl(unknownType1.ts, 163, 1))
>T : Symbol(T, Decl(unknownType1.ts, 167, 13))
>U : Symbol(U, Decl(unknownType1.ts, 167, 15))
>t : Symbol(t, Decl(unknownType1.ts, 167, 35))
>T : Symbol(T, Decl(unknownType1.ts, 167, 13))
>u : Symbol(u, Decl(unknownType1.ts, 167, 40))
>U : Symbol(U, Decl(unknownType1.ts, 167, 15))
>f30 : Symbol(f30, Decl(unknownType1.ts, 164, 1))
>T : Symbol(T, Decl(unknownType1.ts, 168, 13))
>U : Symbol(U, Decl(unknownType1.ts, 168, 15))
>t : Symbol(t, Decl(unknownType1.ts, 168, 35))
>T : Symbol(T, Decl(unknownType1.ts, 168, 13))
>u : Symbol(u, Decl(unknownType1.ts, 168, 40))
>U : Symbol(U, Decl(unknownType1.ts, 168, 15))
let x: {} = t;
>x : Symbol(x, Decl(unknownType1.ts, 168, 7))
>t : Symbol(t, Decl(unknownType1.ts, 167, 35))
>x : Symbol(x, Decl(unknownType1.ts, 169, 7))
>t : Symbol(t, Decl(unknownType1.ts, 168, 35))
let y: {} = u;
>y : Symbol(y, Decl(unknownType1.ts, 169, 7))
>u : Symbol(u, Decl(unknownType1.ts, 167, 40))
>y : Symbol(y, Decl(unknownType1.ts, 170, 7))
>u : Symbol(u, Decl(unknownType1.ts, 168, 40))
}
// Repro from #26796
type Test1 = [unknown] extends [{}] ? true : false; // false
>Test1 : Symbol(Test1, Decl(unknownType1.ts, 170, 1))
>Test1 : Symbol(Test1, Decl(unknownType1.ts, 171, 1))
type IsDefinitelyDefined<T extends unknown> = [T] extends [{}] ? true : false;
>IsDefinitelyDefined : Symbol(IsDefinitelyDefined, Decl(unknownType1.ts, 174, 51))
>T : Symbol(T, Decl(unknownType1.ts, 175, 25))
>T : Symbol(T, Decl(unknownType1.ts, 175, 25))
>IsDefinitelyDefined : Symbol(IsDefinitelyDefined, Decl(unknownType1.ts, 175, 51))
>T : Symbol(T, Decl(unknownType1.ts, 176, 25))
>T : Symbol(T, Decl(unknownType1.ts, 176, 25))
type Test2 = IsDefinitelyDefined<unknown>; // false
>Test2 : Symbol(Test2, Decl(unknownType1.ts, 175, 78))
>IsDefinitelyDefined : Symbol(IsDefinitelyDefined, Decl(unknownType1.ts, 174, 51))
>Test2 : Symbol(Test2, Decl(unknownType1.ts, 176, 78))
>IsDefinitelyDefined : Symbol(IsDefinitelyDefined, Decl(unknownType1.ts, 175, 51))
function oops<T extends unknown>(arg: T): {} {
>oops : Symbol(oops, Decl(unknownType1.ts, 176, 42))
>T : Symbol(T, Decl(unknownType1.ts, 178, 14))
>arg : Symbol(arg, Decl(unknownType1.ts, 178, 33))
>T : Symbol(T, Decl(unknownType1.ts, 178, 14))
>oops : Symbol(oops, Decl(unknownType1.ts, 177, 42))
>T : Symbol(T, Decl(unknownType1.ts, 179, 14))
>arg : Symbol(arg, Decl(unknownType1.ts, 179, 33))
>T : Symbol(T, Decl(unknownType1.ts, 179, 14))
return arg; // Error
>arg : Symbol(arg, Decl(unknownType1.ts, 178, 33))
>arg : Symbol(arg, Decl(unknownType1.ts, 179, 33))
}
+9 -2
View File
@@ -404,8 +404,8 @@ function f26(x: {}, y: unknown, z: any) {
>x : {}
let o2 = { a: 42, ...x, ...y }; // unknown
>o2 : unknown
>{ a: 42, ...x, ...y } : unknown
>o2 : any
>{ a: 42, ...x, ...y } : any
>a : number
>42 : 42
>x : {}
@@ -418,6 +418,13 @@ function f26(x: {}, y: unknown, z: any) {
>42 : 42
>x : {}
>y : unknown
>z : any
let o4 = { a: 42, ...z }; // any
>o4 : any
>{ a: 42, ...z } : any
>a : number
>42 : 42
>z : any
}
@@ -144,6 +144,7 @@ function f26(x: {}, y: unknown, z: any) {
let o1 = { a: 42, ...x }; // { a: number }
let o2 = { a: 42, ...x, ...y }; // unknown
let o3 = { a: 42, ...x, ...y, ...z }; // any
let o4 = { a: 42, ...z }; // any
}
// Functions with unknown return type don't need return expressions