diff --git a/tests/cases/conformance/types/unknown/unknownType1.ts b/tests/cases/conformance/types/unknown/unknownType1.ts new file mode 100644 index 0000000000..ae2ae80dfa --- /dev/null +++ b/tests/cases/conformance/types/unknown/unknownType1.ts @@ -0,0 +1,137 @@ +// @strict: true + +// In an intersection everything absorbs unknown + +type T00 = unknown & null; // null +type T01 = unknown & undefined; // undefined +type T02 = unknown & null & undefined; // null & undefined (which becomes never in union) +type T03 = unknown & string; // string +type T04 = unknown & string[]; // string[] +type T05 = unknown & unknown; // unknown +type T06 = unknown & any; // any + +// In a union an unknown absorbs everything + +type T10 = unknown | null; // unknown +type T11 = unknown | undefined; // unknown +type T12 = unknown | null | undefined; // unknown +type T13 = unknown | string; // unknown +type T14 = unknown | string[]; // unknown +type T15 = unknown | unknown; // unknown +type T16 = unknown | any; // any + +// Type variable and unknown in union and intersection + +type T20 = T & {}; // T & {} +type T21 = T | {}; // T | {} +type T22 = T & unknown; // T +type T23 = T | unknown; // unknown + +// unknown in conditional types + +type T30 = unknown extends T ? true : false; // Deferred +type T31 = T extends unknown ? true : false; // true +type T32 = never extends T ? true : false; // true +type T33 = T extends never ? true : false; // Deferred + +// keyof unknown + +type T40 = keyof any; // string | number | symbol +type T41 = keyof unknown; // string | number | symbol + +// typeof, instanceof, and user defined type predicates + +declare function isFunction(x: unknown): x is Function; + +function f1(x: unknown) { + if (typeof x === "string" || typeof x === "number") { + x; // string | number + } + if (typeof x === "object") { + x; // object + } + if (typeof x === "function") { + x; // object + } + if (x instanceof Error) { + x; // Error + } + if (isFunction(x)) { + x; // Function + } +} + +// Homomorphic mapped type over unknown + +type T50 = { [P in keyof T]: number }; +type T51 = T50; // { [x: string]: number } +type T52 = T50; // { [x: string]: number } + +// Anything is assignable to unknown + +function f2(pAny: any, pNever: never, pT: T) { + let x: unknown; + x = 123; + x = "hello"; + x = [1, 2, 3]; + x = new Error(); + x = x; + x = pAny; + x = pNever; + x = pT; +} + +// unknown assignable only to itself and any + +function f3(x: unknown) { + let v1: any = x; + let v2: unknown = x; + let v3: object = x; // Error + let v4: string = x; // Error + let v5: string[] = x; // Error + let v6: {} = x; // Error + let v7: {} | null | undefined = x; // Error +} + +// Type parameter 'T extends unknown' not related to object + +function f4(x: T) { + let y: object = x; // Error +} + +// Anything but primitive assignable to { [x: string]: unknown } + +function f5(x: { [x: string]: unknown }) { + x = {}; + x = { a: 5 }; + x = [1, 2, 3]; + x = 123; // Error +} + +// Locals of type unknown always considered initialized + +function f6() { + let x: unknown; + let y = x; +} + +// Spread of unknown causes result to be unknown + +function f7(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 +} + +// Functions with unknown return type don't need return expressions + +function f8(): unknown { +} + +// Class properties of type unknown don't need definite assignment + +class C1 { + a: string; // Error + b: unknown; + c: any; +}