1// @strict: true 2// @declaration: true 3 4type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" 5type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c" 6 7type T02 = Exclude<string | number | (() => void), Function>; // string | number 8type T03 = Extract<string | number | (() => void), Function>; // () => void 9 10type T04 = NonNullable<string | number | undefined>; // string | number 11type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[] 12 13function f1<T>(x: T, y: NonNullable<T>) { 14 x = y; 15 y = x; // Error 16} 17 18function f2<T extends string | undefined>(x: T, y: NonNullable<T>) { 19 x = y; 20 y = x; // Error 21 let s1: string = x; // Error 22 let s2: string = y; 23} 24 25function f3<T>(x: Partial<T>[keyof T], y: NonNullable<Partial<T>[keyof T]>) { 26 x = y; 27 y = x; // Error 28} 29 30function f4<T extends { x: string | undefined }>(x: T["x"], y: NonNullable<T["x"]>) { 31 x = y; 32 y = x; // Error 33 let s1: string = x; // Error 34 let s2: string = y; 35} 36 37type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean }; 38 39type T10 = Exclude<Options, { k: "a" | "b" }>; // { k: "c", c: boolean } 40type T11 = Extract<Options, { k: "a" | "b" }>; // { k: "a", a: number } | { k: "b", b: string } 41 42type T12 = Exclude<Options, { k: "a" } | { k: "b" }>; // { k: "c", c: boolean } 43type T13 = Extract<Options, { k: "a" } | { k: "b" }>; // { k: "a", a: number } | { k: "b", b: string } 44 45type T14 = Exclude<Options, { q: "a" }>; // Options 46type T15 = Extract<Options, { q: "a" }>; // never 47 48declare function f5<T extends Options, K extends string>(p: K): Extract<T, { k: K }>; 49let x0 = f5("a"); // { k: "a", a: number } 50 51type OptionsOfKind<K extends Options["k"]> = Extract<Options, { k: K }>; 52 53type T16 = OptionsOfKind<"a" | "b">; // { k: "a", a: number } | { k: "b", b: string } 54 55type Select<T, K extends keyof T, V extends T[K]> = Extract<T, { [P in K]: V }>; 56 57type T17 = Select<Options, "k", "a" | "b">; // // { k: "a", a: number } | { k: "b", b: string } 58 59type TypeName<T> = 60 T extends string ? "string" : 61 T extends number ? "number" : 62 T extends boolean ? "boolean" : 63 T extends undefined ? "undefined" : 64 T extends Function ? "function" : 65 "object"; 66 67type T20 = TypeName<string | (() => void)>; // "string" | "function" 68type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "function" | "object" 69type T22 = TypeName<never>; // never 70type T23 = TypeName<{}>; // "object" 71 72type KnockoutObservable<T> = { object: T }; 73type KnockoutObservableArray<T> = { array: T }; 74 75type KnockedOut<T> = T extends any[] ? KnockoutObservableArray<T[number]> : KnockoutObservable<T>; 76 77type KnockedOutObj<T> = { 78 [P in keyof T]: KnockedOut<T[P]>; 79} 80 81interface Item { 82 id: number; 83 name: string; 84 subitems: string[]; 85} 86 87type KOItem = KnockedOutObj<Item>; 88 89interface Part { 90 id: number; 91 name: string; 92 subparts: Part[]; 93 updatePart(newName: string): void; 94} 95 96type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]; 97type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>; 98 99type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; 100type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>; 101 102type T30 = FunctionProperties<Part>; 103type T31 = NonFunctionProperties<Part>; 104 105function f7<T>(x: T, y: FunctionProperties<T>, z: NonFunctionProperties<T>) { 106 x = y; // Error 107 x = z; // Error 108 y = x; 109 y = z; // Error 110 z = x; 111 z = y; // Error 112} 113 114function f8<T>(x: keyof T, y: FunctionPropertyNames<T>, z: NonFunctionPropertyNames<T>) { 115 x = y; 116 x = z; 117 y = x; // Error 118 y = z; // Error 119 z = x; // Error 120 z = y; // Error 121} 122 123type DeepReadonly<T> = 124 T extends any[] ? DeepReadonlyArray<T[number]> : 125 T extends object ? DeepReadonlyObject<T> : 126 T; 127 128interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} 129 130type DeepReadonlyObject<T> = { 131 readonly [P in NonFunctionPropertyNames<T>]: DeepReadonly<T[P]>; 132}; 133 134function f10(part: DeepReadonly<Part>) { 135 let name: string = part.name; 136 let id: number = part.subparts[0].id; 137 part.id = part.id; // Error 138 part.subparts[0] = part.subparts[0]; // Error 139 part.subparts[0].id = part.subparts[0].id; // Error 140 part.updatePart("hello"); // Error 141} 142 143type ZeroOf<T extends number | string | boolean> = T extends number ? 0 : T extends string ? "" : false; 144 145function zeroOf<T extends number | string | boolean>(value: T) { 146 return <ZeroOf<T>>(typeof value === "number" ? 0 : typeof value === "string" ? "" : false); 147} 148 149function f20<T extends string>(n: number, b: boolean, x: number | boolean, y: T) { 150 zeroOf(5); // 0 151 zeroOf("hello"); // "" 152 zeroOf(true); // false 153 zeroOf(n); // 0 154 zeroOf(b); // False 155 zeroOf(x); // 0 | false 156 zeroOf(y); // ZeroOf<T> 157} 158 159function f21<T extends number | string>(x: T, y: ZeroOf<T>) { 160 let z1: number | string = y; 161 let z2: 0 | "" = y; 162 x = y; // Error 163 y = x; // Error 164} 165 166type T35<T extends { a: string, b: number }> = T[]; 167type T36<T> = T extends { a: string } ? T extends { b: number } ? T35<T> : never : never; 168type T37<T> = T extends { b: number } ? T extends { a: string } ? T35<T> : never : never; 169type T38<T> = [T] extends [{ a: string }] ? [T] extends [{ b: number }] ? T35<T> : never : never; 170 171type Extends<T, U> = T extends U ? true : false; 172type If<C extends boolean, T, F> = C extends true ? T : F; 173type Not<C extends boolean> = If<C, false, true>; 174type And<A extends boolean, B extends boolean> = If<A, B, false>; 175type Or<A extends boolean, B extends boolean> = If<A, true, B>; 176 177type IsString<T> = Extends<T, string>; 178 179type Q1 = IsString<number>; // false 180type Q2 = IsString<"abc">; // true 181type Q3 = IsString<any>; // boolean 182type Q4 = IsString<never>; // never 183 184type N1 = Not<false>; // true 185type N2 = Not<true>; // false 186type N3 = Not<boolean>; // boolean 187 188type A1 = And<false, false>; // false 189type A2 = And<false, true>; // false 190type A3 = And<true, false>; // false 191type A4 = And<true, true>; // true 192type A5 = And<boolean, false>; // false 193type A6 = And<false, boolean>; // false 194type A7 = And<boolean, true>; // boolean 195type A8 = And<true, boolean>; // boolean 196type A9 = And<boolean, boolean>; // boolean 197 198type O1 = Or<false, false>; // false 199type O2 = Or<false, true>; // true 200type O3 = Or<true, false>; // true 201type O4 = Or<true, true>; // true 202type O5 = Or<boolean, false>; // boolean 203type O6 = Or<false, boolean>; // boolean 204type O7 = Or<boolean, true>; // true 205type O8 = Or<true, boolean>; // true 206type O9 = Or<boolean, boolean>; // boolean 207 208type T40 = never extends never ? true : false; // true 209type T41 = number extends never ? true : false; // false 210type T42 = never extends number ? true : false; // true 211 212type IsNever<T> = [T] extends [never] ? true : false; 213 214type T50 = IsNever<never>; // true 215type T51 = IsNever<number>; // false 216type T52 = IsNever<any>; // false 217 218function f22<T>(x: T extends (infer U)[] ? U[] : never) { 219 let e = x[0]; // {} 220} 221 222function f23<T extends string[]>(x: T extends (infer U)[] ? U[] : never) { 223 let e = x[0]; // string 224} 225 226// Repros from #21664 227 228type Eq<T, U> = T extends U ? U extends T ? true : false : false; 229type T60 = Eq<true, true>; // true 230type T61 = Eq<true, false>; // false 231type T62 = Eq<false, true>; // false 232type T63 = Eq<false, false>; // true 233 234type Eq1<T, U> = Eq<T, U> extends false ? false : true; 235type T70 = Eq1<true, true>; // true 236type T71 = Eq1<true, false>; // false 237type T72 = Eq1<false, true>; // false 238type T73 = Eq1<false, false>; // true 239 240type Eq2<T, U> = Eq<T, U> extends true ? true : false; 241type T80 = Eq2<true, true>; // true 242type T81 = Eq2<true, false>; // false 243type T82 = Eq2<false, true>; // false 244type T83 = Eq2<false, false>; // true 245 246// Repro from #21756 247 248type Foo<T> = T extends string ? boolean : number; 249type Bar<T> = T extends string ? boolean : number; 250const convert = <U>(value: Foo<U>): Bar<U> => value; 251 252type Baz<T> = Foo<T>; 253const convert2 = <T>(value: Foo<T>): Baz<T> => value; 254 255function f31<T>() { 256 type T1 = T extends string ? boolean : number; 257 type T2 = T extends string ? boolean : number; 258 var x: T1; 259 var x: T2; 260} 261 262function f32<T, U>() { 263 type T1 = T & U extends string ? boolean : number; 264 type T2 = Foo<T & U>; 265 var z: T1; 266 var z: T2; // Error, T2 is distributive, T1 isn't 267} 268 269function f33<T, U>() { 270 type T1 = Foo<T & U>; 271 type T2 = Bar<T & U>; 272 var z: T1; 273 var z: T2; 274} 275 276// Repro from #21823 277 278type T90<T> = T extends 0 ? 0 : () => 0; 279type T91<T> = T extends 0 ? 0 : () => 0; 280const f40 = <U>(a: T90<U>): T91<U> => a; 281const f41 = <U>(a: T91<U>): T90<U> => a; 282 283type T92<T> = T extends () => 0 ? () => 1 : () => 2; 284type T93<T> = T extends () => 0 ? () => 1 : () => 2; 285const f42 = <U>(a: T92<U>): T93<U> => a; 286const f43 = <U>(a: T93<U>): T92<U> => a; 287 288type T94<T> = T extends string ? true : 42; 289type T95<T> = T extends string ? boolean : number; 290const f44 = <U>(value: T94<U>): T95<U> => value; 291const f45 = <U>(value: T95<U>): T94<U> => value; // Error 292 293// Repro from #21863 294 295function f50() { 296 type Eq<T, U> = T extends U ? U extends T ? true : false : false; 297 type If<S, T, U> = S extends false ? U : T; 298 type Omit<T extends object> = { [P in keyof T]: If<Eq<T[P], never>, never, P>; }[keyof T]; 299 type Omit2<T extends object, U = never> = { [P in keyof T]: If<Eq<T[P], U>, never, P>; }[keyof T]; 300 type A = Omit<{ a: void; b: never; }>; // 'a' 301 type B = Omit2<{ a: void; b: never; }>; // 'a' 302} 303 304// Repro from #21862 305 306type OldDiff<T extends keyof any, U extends keyof any> = ( 307 & { [P in T]: P; } 308 & { [P in U]: never; } 309 & { [x: string]: never; } 310)[T]; 311type NewDiff<T, U> = T extends U ? never : T; 312interface A { 313 a: 'a'; 314} 315interface B1 extends A { 316 b: 'b'; 317 c: OldDiff<keyof this, keyof A>; 318} 319interface B2 extends A { 320 b: 'b'; 321 c: NewDiff<keyof this, keyof A>; 322} 323type c1 = B1['c']; // 'c' | 'b' 324type c2 = B2['c']; // 'c' | 'b' 325 326// Repro from #21929 327 328type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>; 329type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>; 330 331type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" 332type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" 333 334// Repro from #21729 335 336interface Foo2 { foo: string; } 337interface Bar2 { bar: string; } 338type FooBar = Foo2 | Bar2; 339declare interface ExtractFooBar<FB extends FooBar> { } 340 341type Extracted<Struct> = { 342 [K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K]; 343} 344 345// Repro from #22985 346 347type RecursivePartial<T> = { 348 [P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} : 349 T[P] extends object ? RecursivePartial<T[P]> : T[P]; 350}; 351 352declare function assign<T>(o: T, a: RecursivePartial<T>): void; 353 354var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]} 355assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) 356 357// Repros from #23843 358 359type Weird1 = (<U extends boolean>(a: U) => never) extends 360 (<U extends true>(a: U) => never) ? never : never; 361 362type Weird2 = (<U extends boolean>(a: U) => U) extends 363 (<U extends true>(a: U) => infer T) ? T : never; 364