diff --git a/tests/cases/conformance/types/conditional/conditionalTypes1.ts b/tests/cases/conformance/types/conditional/conditionalTypes1.ts new file mode 100644 index 00000000000..d882b4c8bf3 --- /dev/null +++ b/tests/cases/conformance/types/conditional/conditionalTypes1.ts @@ -0,0 +1,198 @@ +// @strict: true +// @declaration: true + +type Diff = T extends U ? never : T; +type Filter = T extends U ? T : never; +type NonNullable = Diff; + +type T00 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" +type T01 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" + +type T02 = Diff void), Function>; // string | number +type T03 = Filter void), Function>; // () => void + +type T04 = NonNullable; // string | number +type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] + +function f1(x: T, y: NonNullable) { + x = y; + y = x; // Error +} + +function f2(x: T, y: NonNullable) { + x = y; + y = x; // Error + let s1: string = x; // Error + let s2: string = y; +} + +function f3(x: Partial[keyof T], y: NonNullable[keyof T]>) { + x = y; + y = x; // Error +} + +type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; + +type T10 = Diff; // { k: "c", c: boolean } +type T11 = Filter; // { k: "a", a: number } | { k: "b", b: string } + +type T12 = Diff; // { k: "c", c: boolean } +type T13 = Filter; // { k: "a", a: number } | { k: "b", b: string } + +type T14 = Diff; // Options +type T15 = Filter; // never + +declare function f4(p: K): Filter; +let x0 = f4("a"); // { k: "a", a: number } + +type OptionsOfKind = Filter; + +type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } + +type Select = Filter; + +type T17 = Select; // // { k: "a", a: number } | { k: "b", b: string } + +type TypeName = + T extends string ? "string" : + T extends number ? "number" : + T extends boolean ? "boolean" : + T extends undefined ? "undefined" : + T extends Function ? "function" : + "object"; + +type T20 = TypeName void)>; // "string" | "function" +type T21 = TypeName; // "string" | "number" | "boolean" | "undefined" | "function" | "object" +type T22 = TypeName; // "string" | "number" | "boolean" | "undefined" | "function" | "object" +type T23 = TypeName<{}>; // "object" + +type KnockoutObservable = { object: T }; +type KnockoutObservableArray = { array: T }; + +type KnockedOut = T extends any[] ? KnockoutObservableArray : KnockoutObservable; + +type KnockedOutObj = { + [P in keyof T]: KnockedOut; +} + +interface Item { + id: number; + name: string; + subitems: string[]; +} + +type KOItem = KnockedOutObj; + +interface Part { + id: number; + name: string; + subparts: Part[]; + updatePart(newName: string): void; +} + +type FunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]; +type FunctionProperties = Pick>; + +type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; +type NonFunctionProperties = Pick>; + +type T30 = FunctionProperties; +type T31 = NonFunctionProperties; + +function f7(x: T, y: FunctionProperties, z: NonFunctionProperties) { + x = y; // Error + x = z; // Error + y = x; + y = z; // Error + z = x; + z = y; // Error +} + +function f8(x: keyof T, y: FunctionPropertyNames, z: NonFunctionPropertyNames) { + x = y; + x = z; + y = x; // Error + y = z; // Error + z = x; // Error + z = y; // Error +} + +type DeepReadonly = + T extends any[] ? DeepReadonlyArray : + T extends object ? DeepReadonlyObject : + T; + +interface DeepReadonlyArray extends ReadonlyArray> {} + +type DeepReadonlyObject = { + readonly [P in NonFunctionPropertyNames]: DeepReadonly; +}; + +function f10(part: DeepReadonly) { + let name: string = part.name; + let id: number = part.subparts[0].id; + part.id = part.id; // Error + part.subparts[0] = part.subparts[0]; // Error + part.subparts[0].id = part.subparts[0].id; // Error + part.updatePart("hello"); // Error +} + +type ZeroOf = T extends number ? 0 : T extends string ? "" : false; + +function zeroOf(value: T) { + return >(typeof value === "number" ? 0 : typeof value === "string" ? "" : false); +} + +function f20(n: number, b: boolean, x: number | boolean, y: T) { + zeroOf(5); // 0 + zeroOf("hello"); // "" + zeroOf(true); // false + zeroOf(n); // 0 + zeroOf(b); // False + zeroOf(x); // 0 | false + zeroOf(y); // ZeroOf +} + +function f21(x: T, y: ZeroOf) { + let z1: number | string = y; + let z2: 0 | "" = y; + x = y; // Error + y = x; // Error +} + +type Extends = T extends U ? true : false; +type If = C extends true ? T : F; +type Not = If; +type And = If; +type Or = If; + +type isString = Extends; + +type Q1 = isString; // false +type Q2 = isString<"abc">; // true +type Q3 = isString; // boolean +type Q4 = isString; // boolean + +type N1 = Not; // true +type N2 = Not; // false +type N3 = Not; // boolean + +type A1 = And; // false +type A2 = And; // false +type A3 = And; // false +type A4 = And; // true +type A5 = And; // false +type A6 = And; // false +type A7 = And; // boolean +type A8 = And; // boolean +type A9 = And; // boolean + +type O1 = Or; // false +type O2 = Or; // true +type O3 = Or; // true +type O4 = Or; // true +type O5 = Or; // boolean +type O6 = Or; // boolean +type O7 = Or; // true +type O8 = Or; // true +type O9 = Or; // boolean