|
| 1 | +import {expectType} from 'tsd'; |
| 2 | +import type {SomeExtend} from '../source/some-extend.d.ts'; |
| 3 | +import type {UnknownArray} from '../source/unknown-array.d.ts'; |
| 4 | + |
| 5 | +expectType<SomeExtend<[], number>>(false); |
| 6 | +expectType<SomeExtend<[1, '2', '3'], number>>(true); // First element matches |
| 7 | +expectType<SomeExtend<['1', '2', 3], number>>(true); // Last element matches |
| 8 | +expectType<SomeExtend<['1', 2, '3'], number>>(true); // Mid element matches |
| 9 | +expectType<SomeExtend<[number, '1', 2, `${number}`], string>>(true); // Multiple elements match |
| 10 | +expectType<SomeExtend<[1, 2, 3], number>>(true); // All elements match |
| 11 | +// Trailing rest element |
| 12 | +expectType<SomeExtend<['2', 1, ...string[]], number>>(true); // Non-rest element matches |
| 13 | +expectType<SomeExtend<['2', '1', ...number[]], number>>(true); // Rest element matches |
| 14 | +// Leading rest element |
| 15 | +expectType<SomeExtend<[...Array<1 | -1>, number, string], string>>(true); // Non-rest element matches |
| 16 | +expectType<SomeExtend<[...Array<1 | -1>, string, string], number>>(true); // Rest element matches |
| 17 | +// Middle rest element |
| 18 | +expectType<SomeExtend<[string, number, ...string[], string, string], number>>(true); // Non-rest element before rest element matches |
| 19 | +expectType<SomeExtend<[string, string, ...string[], number, string], number>>(true); // Non-rest element after rest element matches |
| 20 | +expectType<SomeExtend<[string, ...number[], string, string], number>>(true); // Rest element matches |
| 21 | + |
| 22 | +expectType<SomeExtend<['1', '2', '3'], number>>(false); |
| 23 | +expectType<SomeExtend<[1, 2, 3], string>>(false); |
| 24 | +expectType<SomeExtend<[1, 2, 3, ...string[]], bigint>>(false); |
| 25 | +expectType<SomeExtend<[...bigint[], true, false], number | string>>(false); |
| 26 | +expectType<SomeExtend<[1, 2, ...number[], '1', 3], true>>(false); |
| 27 | +expectType<SomeExtend<['1', '2', ...bigint[]], number>>(false); |
| 28 | + |
| 29 | +// Union targets |
| 30 | +expectType<SomeExtend<['1', '2', 3], number | bigint>>(true); |
| 31 | +expectType<SomeExtend<[1, false, 0, true, 1], boolean>>(true); |
| 32 | +expectType<SomeExtend<[...bigint[], number, string], number | string>>(true); |
| 33 | + |
| 34 | +// Union type elements |
| 35 | +expectType<SomeExtend<[number, string | number], string>>({} as boolean); |
| 36 | +expectType<SomeExtend<[false, false, false, boolean], true>>({} as boolean); |
| 37 | +expectType<SomeExtend<[true, true, boolean, true], false>>({} as boolean); |
| 38 | +expectType<SomeExtend<[1, 2n, number | bigint, 3n], string>>(false); |
| 39 | +expectType<SomeExtend<['1', '2', number | bigint, '3'], number | bigint>>(true); |
| 40 | +expectType<SomeExtend<[true, false, true, ...Array<string | undefined>], string | number>>({} as boolean); |
| 41 | +expectType<SomeExtend<['foo', ...Array<number | string>, 'bar'], bigint | undefined>>(false); |
| 42 | + |
| 43 | +// Readonly arrays |
| 44 | +expectType<SomeExtend<readonly [], number>>(false); |
| 45 | +expectType<SomeExtend<readonly ['1', 2, '3'], number>>(true); |
| 46 | +expectType<SomeExtend<readonly ['1', '2', '3'], number>>(false); |
| 47 | +expectType<SomeExtend<readonly ['^', ...number[], '$'], number>>(true); |
| 48 | + |
| 49 | +// Optional elements |
| 50 | +// If `exactOptionalPropertyTypes` were disabled, the target type would need an additional `| undefined` for a successful match. |
| 51 | +// For example, `SomeExtend<['1'?, 2?], number>` would return `boolean`. To make it return `true`, the target type must be `number | undefined`. |
| 52 | +expectType<SomeExtend<['1'?, '2'?, 3?], number>>(true); |
| 53 | +expectType<SomeExtend<['1'?, (2 | undefined)?], number>>({} as boolean); |
| 54 | +expectType<SomeExtend<[1?, '2'?, 3?], string | undefined>>(true); |
| 55 | +expectType<SomeExtend<[1, 2?, 3?, ...string[]], string>>(true); |
| 56 | +expectType<SomeExtend<['1', '2'?, '3'?, ...Array<number | undefined>], number>>({} as boolean); |
| 57 | +expectType<SomeExtend<[1?, 2?, 3?, ...boolean[]], string>>(false); |
| 58 | + |
| 59 | +// Labelled tuples |
| 60 | +expectType<SomeExtend<[x: string, y: number], string>>(true); |
| 61 | +expectType<SomeExtend<[x?: number, y?: number], string>>(false); |
| 62 | +expectType<SomeExtend<[x?: string, y?: string, ...rest: number[]], number>>(true); |
| 63 | +expectType<SomeExtend<[...rest: number[], z: string], string>>(true); |
| 64 | +expectType<SomeExtend<[...rest: number[], z: string], bigint>>(false); |
| 65 | + |
| 66 | +// Non-tuple arrays |
| 67 | +expectType<SomeExtend<string[], string>>(true); |
| 68 | +expectType<SomeExtend<Array<string | number>, number>>({} as boolean); |
| 69 | +expectType<SomeExtend<ReadonlyArray<string | undefined>, string>>({} as boolean); |
| 70 | +expectType<SomeExtend<[...readonly boolean[]], string>>(false); |
| 71 | + |
| 72 | +// Unions |
| 73 | +expectType<SomeExtend<['1', '2', 3] | ['4', 5, '6'], number>>(true); // Both `true` |
| 74 | +expectType<SomeExtend<[1, 2, 3] | ['4', '5', '6'], bigint>>(false); // Both `false` |
| 75 | +expectType<SomeExtend<['1', '2', '3'] | ['1', '2', 3], number>>({} as boolean); // One `true`, one `false` |
| 76 | +expectType<SomeExtend<[true, false] | [false, boolean], true>>({} as boolean); // One `true`, one `boolean` |
| 77 | +expectType<SomeExtend<[false, false] | [boolean, false], true>>({} as boolean); // One `false`, one `boolean` |
| 78 | + |
| 79 | +expectType<SomeExtend<[string, string, ...number[]] | [number, string, ...number[]], number>>(true); |
| 80 | +expectType<SomeExtend<readonly [(number | bigint)?, ...string[]] | [0, 'a', 'b'] | [...ReadonlyArray<string | number>, 1], true>>(false); |
| 81 | +expectType<SomeExtend<number[] | [...ReadonlyArray<string | number>, number], string>>({} as boolean); |
| 82 | +expectType<SomeExtend<readonly number[] | [...rest: string[], l1: string, l2: string] | [(number | string)?, string?, ...string[]], number>>( |
| 83 | + {} as boolean, |
| 84 | +); |
| 85 | + |
| 86 | +// Boundary cases |
| 87 | +expectType<SomeExtend<[], any>>(false); |
| 88 | +expectType<SomeExtend<[], never>>(false); |
| 89 | +// `never` target |
| 90 | +expectType<SomeExtend<[number, string, boolean], never>>(false); |
| 91 | +expectType<SomeExtend<[number, string, never], never>>(true); |
| 92 | +expectType<SomeExtend<[number, string, any], never>>({} as boolean); |
| 93 | +// `any` target |
| 94 | +expectType<SomeExtend<[number], any>>(true); |
| 95 | +expectType<SomeExtend<[never], any>>(true); |
| 96 | +expectType<SomeExtend<[any], any>>(true); |
| 97 | +// `never` and `any` elements |
| 98 | +expectType<SomeExtend<[1, 2, never], string>>(false); |
| 99 | +expectType<SomeExtend<[1, 2, any], string>>({} as boolean); |
| 100 | +// `never[]` and `any[]` elements |
| 101 | +expectType<SomeExtend<[1, 2, ...any[]], string>>({} as boolean); |
| 102 | +expectType<SomeExtend<[1, 2, ...any[], 3, 4], string>>({} as boolean); |
| 103 | +expectType<SomeExtend<[...any[], 3, 4], string>>({} as boolean); |
| 104 | +expectType<SomeExtend<any[], number>>({} as boolean); |
| 105 | +expectType<SomeExtend<[1, 2, ...never[]], string>>(false); |
| 106 | +expectType<SomeExtend<[1, 2, ...never[], 3, 4], string>>(false); |
| 107 | +expectType<SomeExtend<[...never[], 1, 2], string>>(false); |
| 108 | +expectType<SomeExtend<never[], number>>(false); |
| 109 | + |
| 110 | +// === strictNever: false === |
| 111 | +type NonStrictNeverSomeExtend<TArray extends UnknownArray, Type> = SomeExtend<TArray, Type, {strictNever: false}>; |
| 112 | + |
| 113 | +// `never` elements |
| 114 | +expectType<NonStrictNeverSomeExtend<[1, 2, never], string>>(true); |
| 115 | +// `never[]` elements |
| 116 | +expectType<NonStrictNeverSomeExtend<[1, 2, ...never[]], string>>(true); |
| 117 | +expectType<NonStrictNeverSomeExtend<[1, 2, ...never[], 3, 4], string>>(true); |
| 118 | +expectType<NonStrictNeverSomeExtend<[...never[], 1, 2], string>>(true); |
| 119 | +expectType<NonStrictNeverSomeExtend<never[], number>>(true); |
| 120 | + |
| 121 | +expectType<SomeExtend<any, never>>(false); |
| 122 | +expectType<SomeExtend<never, any>>(false); |
0 commit comments