diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5d12634 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/README.md b/README.md index 253c13d..e0f3740 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ const test: WeatherForecast = { ### XORing more than two types -If you want to create a type as the product of the logical XOR operation between multiple types (more than two), then nest the generic params. +If you want to create a type as the product of the logical XOR operation between multiple types (more than two and up to even 100), then just pass them as additional comma-separated generic params. ```typescript import type { XOR } from 'ts-xor' @@ -145,7 +145,7 @@ interface A { a: string } interface B { b: string } interface C { c: string } -let test: XOR> +let test: XOR test = { a: '' } // OK test = { b: '' } // OK diff --git a/src/index.ts b/src/index.ts index 30a7c10..e73ee8b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1 @@ -export * from './types/xor.js' +export type * from './types/xor.js' diff --git a/src/types/evalIfNotUnknown.ts b/src/types/evalIfNotUnknown.ts new file mode 100644 index 0000000..3f2f868 --- /dev/null +++ b/src/types/evalIfNotUnknown.ts @@ -0,0 +1,4 @@ + /** + * Skip evaluating `U` if `T` is `unknown`. + */ + export type EvalIfNotUnknown = unknown extends T ? never : U; diff --git a/src/types/xor.ts b/src/types/xor.ts index 3e32b8b..0317d29 100644 --- a/src/types/xor.ts +++ b/src/types/xor.ts @@ -1,16 +1,15 @@ -import { Prettify } from './prettify.js' -import { Without } from './without.js' +import type { EvalIfNotUnknown } from './evalIfNotUnknown.js' +import type { Prettify } from './prettify.js' +import type { Without } from './without.js' /** - * Restrict using either exclusively the keys of T or exclusively the keys of U. + * Restrict using either exclusively the keys of `T` or exclusively the keys of `U`. * - * No unique keys of T can be used simultaneously with any unique keys of U. + * No unique keys of `T` can be used simultaneously with any unique keys of `U`. * * Example: - * `const myVar: XOR` + * `const myVar: XOR<{ data: object }, { error: object }>` * * More: https://github.com/maninak/ts-xor/tree/master#description */ -export type XOR = (T | U) extends object - ? (Prettify & U>) | (Prettify & T>) - : T | U +export type XOR = Prettify<(Without & A) | (Without & B) | EvalIfNotUnknown & C> | EvalIfNotUnknown & D> | EvalIfNotUnknown & E> | EvalIfNotUnknown & F> | EvalIfNotUnknown & G> | EvalIfNotUnknown & H> | EvalIfNotUnknown & I> | EvalIfNotUnknown & J> | EvalIfNotUnknown & K> | EvalIfNotUnknown & L> | EvalIfNotUnknown & M> | EvalIfNotUnknown & N> | EvalIfNotUnknown & O> | EvalIfNotUnknown & P> | EvalIfNotUnknown & Q> | EvalIfNotUnknown & R> | EvalIfNotUnknown & S> | EvalIfNotUnknown & T> | EvalIfNotUnknown & AA> | EvalIfNotUnknown & AB> | EvalIfNotUnknown & AC> | EvalIfNotUnknown & AD> | EvalIfNotUnknown & AE> | EvalIfNotUnknown & AF> | EvalIfNotUnknown & AG> | EvalIfNotUnknown & AH> | EvalIfNotUnknown & AI> | EvalIfNotUnknown & AJ> | EvalIfNotUnknown & AK> | EvalIfNotUnknown & AL> | EvalIfNotUnknown & AM> | EvalIfNotUnknown & AN> | EvalIfNotUnknown & AO> | EvalIfNotUnknown & AP> | EvalIfNotUnknown & AQ> | EvalIfNotUnknown & AR> | EvalIfNotUnknown & AS> | EvalIfNotUnknown & AT> | EvalIfNotUnknown & BA> | EvalIfNotUnknown & BB> | EvalIfNotUnknown & BC> | EvalIfNotUnknown & BD> | EvalIfNotUnknown & BE> | EvalIfNotUnknown & BF> | EvalIfNotUnknown & BG> | EvalIfNotUnknown & BH> | EvalIfNotUnknown & BI> | EvalIfNotUnknown & BJ> | EvalIfNotUnknown & BK> | EvalIfNotUnknown & BL> | EvalIfNotUnknown & BM> | EvalIfNotUnknown & BN> | EvalIfNotUnknown & BO> | EvalIfNotUnknown & BP> | EvalIfNotUnknown & BQ> | EvalIfNotUnknown & BR> | EvalIfNotUnknown & BS> | EvalIfNotUnknown & BT> | EvalIfNotUnknown & CA> | EvalIfNotUnknown & CB> | EvalIfNotUnknown & CC> | EvalIfNotUnknown & CD> | EvalIfNotUnknown & CE> | EvalIfNotUnknown & CF> | EvalIfNotUnknown & CG> | EvalIfNotUnknown & CH> | EvalIfNotUnknown & CI> | EvalIfNotUnknown & CJ> | EvalIfNotUnknown & CK> | EvalIfNotUnknown & CL> | EvalIfNotUnknown & CM> | EvalIfNotUnknown & CN> | EvalIfNotUnknown & CO> | EvalIfNotUnknown & CP> | EvalIfNotUnknown & CQ> | EvalIfNotUnknown & CR> | EvalIfNotUnknown & CS> | EvalIfNotUnknown & CT> | EvalIfNotUnknown & DA> | EvalIfNotUnknown & DB> | EvalIfNotUnknown & DC> | EvalIfNotUnknown & DD> | EvalIfNotUnknown & DE> | EvalIfNotUnknown & DF> | EvalIfNotUnknown & DG> | EvalIfNotUnknown & DH> | EvalIfNotUnknown & DI> | EvalIfNotUnknown & DJ> | EvalIfNotUnknown & DK> | EvalIfNotUnknown & DL> | EvalIfNotUnknown & DM> | EvalIfNotUnknown & DN> | EvalIfNotUnknown & DO> | EvalIfNotUnknown & DP> | EvalIfNotUnknown & DQ> | EvalIfNotUnknown & DR> | EvalIfNotUnknown & DS> | EvalIfNotUnknown & DT> | EvalIfNotUnknown & EA> | EvalIfNotUnknown & EB> | EvalIfNotUnknown & EC> | EvalIfNotUnknown & ED> | EvalIfNotUnknown & EE> | EvalIfNotUnknown & EF> | EvalIfNotUnknown & EG> | EvalIfNotUnknown & EH> | EvalIfNotUnknown & EI> | EvalIfNotUnknown & EJ> | EvalIfNotUnknown & EK> | EvalIfNotUnknown & EL> | EvalIfNotUnknown & EM> | EvalIfNotUnknown & EN> | EvalIfNotUnknown & EO> | EvalIfNotUnknown & EP> | EvalIfNotUnknown & EQ> | EvalIfNotUnknown & ER> | EvalIfNotUnknown & ES> | EvalIfNotUnknown & ET> | EvalIfNotUnknown & FA> | EvalIfNotUnknown & FB> | EvalIfNotUnknown & FC> | EvalIfNotUnknown & FD> | EvalIfNotUnknown & FE> | EvalIfNotUnknown & FF> | EvalIfNotUnknown & FG> | EvalIfNotUnknown & FH> | EvalIfNotUnknown & FI> | EvalIfNotUnknown & FJ> | EvalIfNotUnknown & FK> | EvalIfNotUnknown & FL> | EvalIfNotUnknown & FM> | EvalIfNotUnknown & FN> | EvalIfNotUnknown & FO> | EvalIfNotUnknown & FP> | EvalIfNotUnknown & FQ> | EvalIfNotUnknown & FR> | EvalIfNotUnknown & FS> | EvalIfNotUnknown & FT> | EvalIfNotUnknown & GA> | EvalIfNotUnknown & GB> | EvalIfNotUnknown & GC> | EvalIfNotUnknown & GD> | EvalIfNotUnknown & GE> | EvalIfNotUnknown & GF> | EvalIfNotUnknown & GG> | EvalIfNotUnknown & GH> | EvalIfNotUnknown & GI> | EvalIfNotUnknown & GJ> | EvalIfNotUnknown & GK> | EvalIfNotUnknown & GL> | EvalIfNotUnknown & GM> | EvalIfNotUnknown & GN> | EvalIfNotUnknown & GO> | EvalIfNotUnknown & GP> | EvalIfNotUnknown & GQ> | EvalIfNotUnknown & GR> | EvalIfNotUnknown & GS> | EvalIfNotUnknown & GT> | EvalIfNotUnknown & HA> | EvalIfNotUnknown & HB> | EvalIfNotUnknown & HC> | EvalIfNotUnknown & HD> | EvalIfNotUnknown & HE> | EvalIfNotUnknown & HF> | EvalIfNotUnknown & HG> | EvalIfNotUnknown & HH> | EvalIfNotUnknown & HI> | EvalIfNotUnknown & HJ> | EvalIfNotUnknown & HK> | EvalIfNotUnknown & HL> | EvalIfNotUnknown & HM> | EvalIfNotUnknown & HN> | EvalIfNotUnknown & HO> | EvalIfNotUnknown & HP> | EvalIfNotUnknown & HQ> | EvalIfNotUnknown & HR> | EvalIfNotUnknown & HS> | EvalIfNotUnknown & HT> | EvalIfNotUnknown & IA> | EvalIfNotUnknown & IB> | EvalIfNotUnknown & IC> | EvalIfNotUnknown & ID> | EvalIfNotUnknown & IE> | EvalIfNotUnknown & IF> | EvalIfNotUnknown & IG> | EvalIfNotUnknown & IH> | EvalIfNotUnknown & II> | EvalIfNotUnknown & IJ> | EvalIfNotUnknown & IK> | EvalIfNotUnknown & IL> | EvalIfNotUnknown & IM> | EvalIfNotUnknown & IN> | EvalIfNotUnknown & IO> | EvalIfNotUnknown & IP> | EvalIfNotUnknown & IQ> | EvalIfNotUnknown & IR> | EvalIfNotUnknown & IS> | EvalIfNotUnknown & IT>> diff --git a/src/xorFactory.js b/src/xorFactory.js new file mode 100644 index 0000000..dc7b7b1 --- /dev/null +++ b/src/xorFactory.js @@ -0,0 +1,117 @@ +const ts = require('typescript') + +const xorParamCount = 200 +const countOfUniqueLetters = 20 +/** + * Contains ['A', 'B', ..., ] + */ +const uniqueLetters = [...Array(countOfUniqueLetters).keys()] + .map(i => String.fromCharCode(i + 65)) +const allParamNames = generateUniquePermutations(uniqueLetters, xorParamCount) +const [,, ...paramNamesWithoutANorB] = allParamNames + +function createXor() { + const modifiers = [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)] + const name = ts.factory.createIdentifier('XOR') + const typeParams = createXorParams() + const type = createXorType() + + return ts.factory.createTypeAliasDeclaration(modifiers, name, typeParams, type) +} + +function createXorParams() { + const xorParams = [ + ts.factory.createTypeParameterDeclaration(undefined, ts.factory.createIdentifier('A')), + ts.factory.createTypeParameterDeclaration(undefined, ts.factory.createIdentifier('B')), + ...paramNamesWithoutANorB.map((letter) => ts.factory.createTypeParameterDeclaration( + undefined, + ts.factory.createIdentifier(letter), + undefined, + ts.factory.createTypeReferenceNode('unknown') + )) + ] + + return xorParams +} + +function createXorType() { + const unionOfWithouts = ts.factory.createUnionTypeNode([ + createWithoutLettersIntersectingLetter( + allParamNames.filter((letterToExclude) => letterToExclude !== 'A'), + 'A', + ), + createWithoutLettersIntersectingLetter( + allParamNames.filter((letterToExclude) => letterToExclude !== 'B'), + 'B', + ), + ...paramNamesWithoutANorB.map( + (letter) => ts.factory.createTypeReferenceNode( + 'EvalIfNotUnknown', + [ + ts.factory.createTypeReferenceNode(letter), + createWithoutLettersIntersectingLetter( + allParamNames.filter((letterToExclude) => letterToExclude !== letter), + letter, + ), + ] + ) + ) + ]) + + const type = ts.factory.createTypeReferenceNode('Prettify', [unionOfWithouts]) + + return type +} + +/** + * @param {string[]} lettersExcludingLetter + * @param {string} excludedLetter + */ +function createWithoutLettersIntersectingLetter(lettersExcludingLetter, excludedLetter) { + const withoutLettersIntersectingLetter = ts.factory.createIntersectionTypeNode([ + createWithout(lettersExcludingLetter, excludedLetter), + ts.factory.createTypeReferenceNode(excludedLetter) + ]) + + return withoutLettersIntersectingLetter +} + +/** + * @param {string[]} lettersExcludingLetter + * @param {string} excludedLetter + */ +function createWithout(lettersExcludingLetter, excludedLetter) { + const type = ts.factory.createTypeReferenceNode('Without', [ + ts.factory.createIntersectionTypeNode( + lettersExcludingLetter.map((letter) => ts.factory.createTypeReferenceNode(letter)) + ), + ts.factory.createTypeReferenceNode(excludedLetter) + ]) + + return type +} + +/** + * @param {string[]} symbolPool + * @param {number} countParamNamesToGenerate + */ +function generateUniquePermutations(symbolPool, countParamNamesToGenerate) { + const generateItem = (index) => { + if (index < 0) { + return '' + } + const remainder = index % 20 + return generateItem(Math.floor(index / 20) - 1) + symbolPool[remainder] + } + + const result = Array.from({ length: countParamNamesToGenerate }, (_, i) => generateItem(i)) + + return result +} + +const resultFile = ts.createSourceFile('source.ts', '', ts.ScriptTarget.ESNext, false, ts.ScriptKind.TS) +const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }) + +const result = printer.printNode(ts.EmitHint.Unspecified, createXor(), resultFile) + +console.log(result) diff --git a/test/control-std-union-without-xor/setup.ts b/test/control-std-union-without-xor/setup.ts index 67dac26..6f923b8 100644 --- a/test/control-std-union-without-xor/setup.ts +++ b/test/control-std-union-without-xor/setup.ts @@ -1,9 +1,4 @@ -interface A { - a: string -} - -interface B { - b: string -} +interface A { a: string } +interface B { b: string } export type A_OR_B = A | B diff --git a/test/four-xored-types/has-keys-of-A-and-C.spec.ts b/test/four-xored-types/has-keys-of-A-and-C.spec.ts new file mode 100644 index 0000000..7ef0b30 --- /dev/null +++ b/test/four-xored-types/has-keys-of-A-and-C.spec.ts @@ -0,0 +1,6 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +// @ts-expect-error +const test: XOR_A_B_C_D = { a: '', c: '' } +// @ts-expect-error +const testNested: XOR_A_B_C_D_Nested = { a: '', c: '' } diff --git a/test/four-xored-types/has-keys-of-A-and-D.spec.ts b/test/four-xored-types/has-keys-of-A-and-D.spec.ts new file mode 100644 index 0000000..5443e55 --- /dev/null +++ b/test/four-xored-types/has-keys-of-A-and-D.spec.ts @@ -0,0 +1,6 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +// @ts-expect-error +const test: XOR_A_B_C_D = { a: '', d: '' } +// @ts-expect-error +const testNested: XOR_A_B_C_D_Nested = { a: '', d: '' } diff --git a/test/four-xored-types/has-keys-of-A.spec.ts b/test/four-xored-types/has-keys-of-A.spec.ts new file mode 100644 index 0000000..164032f --- /dev/null +++ b/test/four-xored-types/has-keys-of-A.spec.ts @@ -0,0 +1,4 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +const test: XOR_A_B_C_D = { a: '' } // OK +const testNested: XOR_A_B_C_D_Nested = { a: '' } // OK diff --git a/test/four-xored-types/has-keys-of-B.spec.ts b/test/four-xored-types/has-keys-of-B.spec.ts new file mode 100644 index 0000000..970e58f --- /dev/null +++ b/test/four-xored-types/has-keys-of-B.spec.ts @@ -0,0 +1,4 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +const test: XOR_A_B_C_D = { b: '' } // OK +const testNested: XOR_A_B_C_D_Nested = { b: '' } // OK diff --git a/test/four-xored-types/has-keys-of-C-and-D.spec.ts b/test/four-xored-types/has-keys-of-C-and-D.spec.ts new file mode 100644 index 0000000..adbf77f --- /dev/null +++ b/test/four-xored-types/has-keys-of-C-and-D.spec.ts @@ -0,0 +1,6 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +// @ts-expect-error +const test: XOR_A_B_C_D = { c: '', d: '' } +// @ts-expect-error +const testNested: XOR_A_B_C_D_Nested = { c: '', d: '' } diff --git a/test/four-xored-types/has-keys-of-C.spec.ts b/test/four-xored-types/has-keys-of-C.spec.ts new file mode 100644 index 0000000..510e4bb --- /dev/null +++ b/test/four-xored-types/has-keys-of-C.spec.ts @@ -0,0 +1,4 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +const test: XOR_A_B_C_D = { c: '' } // OK +const testNested: XOR_A_B_C_D_Nested = { c: '' } // OK diff --git a/test/four-xored-types/has-keys-of-D.spec.ts b/test/four-xored-types/has-keys-of-D.spec.ts new file mode 100644 index 0000000..f414eee --- /dev/null +++ b/test/four-xored-types/has-keys-of-D.spec.ts @@ -0,0 +1,4 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +const test: XOR_A_B_C_D = { d: '' } // OK +const testNested: XOR_A_B_C_D_Nested = { d: '' } // OK diff --git a/test/four-xored-types/has-no-keys.spec.ts b/test/four-xored-types/has-no-keys.spec.ts new file mode 100644 index 0000000..45f4df9 --- /dev/null +++ b/test/four-xored-types/has-no-keys.spec.ts @@ -0,0 +1,6 @@ +import { XOR_A_B_C_D, XOR_A_B_C_D_Nested } from './setup' + +// @ts-expect-error +const test: XOR_A_B_C_D = {} +// @ts-expect-error +const testNested: XOR_A_B_C_D_Nested = {} diff --git a/test/four-xored-types/setup.ts b/test/four-xored-types/setup.ts new file mode 100644 index 0000000..23f2162 --- /dev/null +++ b/test/four-xored-types/setup.ts @@ -0,0 +1,9 @@ +import type { XOR } from '../../src' + +interface A { a: string } +interface B { b: string } +interface C { c: string } +interface D { d: string } + +export type XOR_A_B_C_D = XOR +export type XOR_A_B_C_D_Nested = XOR>> diff --git a/test/multiple-xored-types/has-keys-of-A-and-C.spec.ts b/test/multiple-xored-types/has-keys-of-A-and-C.spec.ts deleted file mode 100644 index ea1192c..0000000 --- a/test/multiple-xored-types/has-keys-of-A-and-C.spec.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { A_XOR_B_XOR_C } from './setup' - -// @ts-expect-error -const test: A_XOR_B_XOR_C = { a: '', c: '' } diff --git a/test/multiple-xored-types/has-keys-of-A.spec.ts b/test/multiple-xored-types/has-keys-of-A.spec.ts deleted file mode 100644 index 2737d23..0000000 --- a/test/multiple-xored-types/has-keys-of-A.spec.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { A_XOR_B_XOR_C } from './setup' - -const test: A_XOR_B_XOR_C = { a: '' } // OK diff --git a/test/multiple-xored-types/has-keys-of-B.spec.ts b/test/multiple-xored-types/has-keys-of-B.spec.ts deleted file mode 100644 index 09a0c9d..0000000 --- a/test/multiple-xored-types/has-keys-of-B.spec.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { A_XOR_B_XOR_C } from './setup' - -const test: A_XOR_B_XOR_C = { b: '' } // OK diff --git a/test/multiple-xored-types/has-keys-of-C.spec.ts b/test/multiple-xored-types/has-keys-of-C.spec.ts deleted file mode 100644 index 6b27f6e..0000000 --- a/test/multiple-xored-types/has-keys-of-C.spec.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { A_XOR_B_XOR_C } from './setup' - -const test: A_XOR_B_XOR_C = { c: '' } // OK diff --git a/test/multiple-xored-types/has-no-keys.spec.ts b/test/multiple-xored-types/has-no-keys.spec.ts deleted file mode 100644 index 8455662..0000000 --- a/test/multiple-xored-types/has-no-keys.spec.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { A_XOR_B_XOR_C } from './setup' - -// @ts-expect-error -const test: A_XOR_B_XOR_C = {} diff --git a/test/multiple-xored-types/setup.ts b/test/multiple-xored-types/setup.ts deleted file mode 100644 index ca695f2..0000000 --- a/test/multiple-xored-types/setup.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { XOR } from './../../src' - -interface A { - a: string -} - -interface B { - b: string -} - -interface C { - c: string -} - -export type A_XOR_B_XOR_C = XOR> diff --git a/test/shared-and-xored-members/setup.ts b/test/shared-and-xored-members/setup.ts index d21b7e2..d5caf7d 100644 --- a/test/shared-and-xored-members/setup.ts +++ b/test/shared-and-xored-members/setup.ts @@ -1,4 +1,4 @@ -import { XOR } from './../../src' +import type { XOR } from './../../src' type ForecastAccuracy = XOR<{ '1h': number }, { '3h': number }> diff --git a/test/single-member-objects/setup.ts b/test/single-member-objects/setup.ts index 9d54d57..0ff82d7 100644 --- a/test/single-member-objects/setup.ts +++ b/test/single-member-objects/setup.ts @@ -1,11 +1,6 @@ -import { XOR } from './../../src' +import type { XOR } from './../../src' -interface A { - a: string -} - -interface B { - b: string -} +interface A { a: string } +interface B { b: string } export type A_XOR_B = XOR diff --git a/test/two-hundred-xored-types/has-keys-of-first-and-keys-of-last.spec.ts b/test/two-hundred-xored-types/has-keys-of-first-and-keys-of-last.spec.ts new file mode 100644 index 0000000..3c1b545 --- /dev/null +++ b/test/two-hundred-xored-types/has-keys-of-first-and-keys-of-last.spec.ts @@ -0,0 +1,4 @@ +import { XOR_200 } from './setup'; + +// @ts-expect-error +const test: XOR_200 = { a: 0, zdt: 0 } diff --git a/test/two-hundred-xored-types/has-keys-of-first.spec.ts b/test/two-hundred-xored-types/has-keys-of-first.spec.ts new file mode 100644 index 0000000..069b5d3 --- /dev/null +++ b/test/two-hundred-xored-types/has-keys-of-first.spec.ts @@ -0,0 +1,3 @@ +import { XOR_200 } from './setup'; + +const test: XOR_200 = { a: 0 } // OK diff --git a/test/two-hundred-xored-types/has-keys-of-last-two.spec.ts b/test/two-hundred-xored-types/has-keys-of-last-two.spec.ts new file mode 100644 index 0000000..7686dba --- /dev/null +++ b/test/two-hundred-xored-types/has-keys-of-last-two.spec.ts @@ -0,0 +1,4 @@ +import { XOR_200 } from './setup'; + +// @ts-expect-error +const test: XOR_200 = { zds: 0, zdt: 0 } diff --git a/test/two-hundred-xored-types/has-keys-of-last.spec.ts b/test/two-hundred-xored-types/has-keys-of-last.spec.ts new file mode 100644 index 0000000..f073fc6 --- /dev/null +++ b/test/two-hundred-xored-types/has-keys-of-last.spec.ts @@ -0,0 +1,3 @@ +import { XOR_200 } from './setup'; + +const test: XOR_200 = { zdt: 0 } // OK diff --git a/test/two-hundred-xored-types/has-two-hundred-one-params.spec.ts b/test/two-hundred-xored-types/has-two-hundred-one-params.spec.ts new file mode 100644 index 0000000..a858457 --- /dev/null +++ b/test/two-hundred-xored-types/has-two-hundred-one-params.spec.ts @@ -0,0 +1,26 @@ +import type { XOR } from '../../src' + +// @ts-expect-error +export type XOR_200 = XOR< + {EXTRANEOUS: 0}, + {a: 0}, {b: 0}, {c: 0}, {d: 0}, {e: 0}, {f: 0}, {g: 0}, {h: 0}, {i: 0}, {j: 0}, + {k: 0}, {l: 0}, {m: 0}, {n: 0}, {o: 0}, {p: 0}, {q: 0}, {r: 0}, {s: 0}, {t: 0}, + {aa: 0}, {ab: 0}, {ac: 0}, {ad: 0}, {ae: 0}, {af: 0}, {ag: 0}, {ah: 0}, {ai: 0}, {aj: 0}, + {ak: 0}, {al: 0}, {am: 0}, {an: 0}, {ao: 0}, {ap: 0}, {aq: 0}, {ar: 0}, {as: 0}, {at: 0}, + {ba: 0}, {bb: 0}, {bc: 0}, {bd: 0}, {be: 0}, {bf: 0}, {bg: 0}, {bh: 0}, {bi: 0}, {bj: 0}, + {bk: 0}, {bl: 0}, {bm: 0}, {bn: 0}, {bo: 0}, {bp: 0}, {bq: 0}, {br: 0}, {bs: 0}, {bt: 0}, + {ca: 0}, {cb: 0}, {cc: 0}, {cd: 0}, {ce: 0}, {cf: 0}, {cg: 0}, {ch: 0}, {ci: 0}, {cj: 0}, + {ck: 0}, {cl: 0}, {cm: 0}, {cn: 0}, {co: 0}, {cp: 0}, {cq: 0}, {cr: 0}, {cs: 0}, {ct: 0}, + {da: 0}, {db: 0}, {dc: 0}, {dd: 0}, {de: 0}, {df: 0}, {dg: 0}, {dh: 0}, {di: 0}, {dj: 0}, + {dk: 0}, {dl: 0}, {dm: 0}, {dn: 0}, {do: 0}, {dp: 0}, {dq: 0}, {dr: 0}, {ds: 0}, {dt: 0}, + {za: 0}, {zb: 0}, {zc: 0}, {zd: 0}, {ze: 0}, {zf: 0}, {zg: 0}, {zh: 0}, {zi: 0}, {zj: 0}, + {zk: 0}, {zl: 0}, {zm: 0}, {zn: 0}, {zo: 0}, {zp: 0}, {zq: 0}, {zr: 0}, {zs: 0}, {zt: 0}, + {zaa: 0}, {zab: 0}, {zac: 0}, {zad: 0}, {zae: 0}, {zaf: 0}, {zag: 0}, {zah: 0}, {zai: 0}, {zaj: 0}, + {zak: 0}, {zal: 0}, {zam: 0}, {zan: 0}, {zao: 0}, {zap: 0}, {zaq: 0}, {zar: 0}, {zas: 0}, {zat: 0}, + {zba: 0}, {zbb: 0}, {zbc: 0}, {zbd: 0}, {zbe: 0}, {zbf: 0}, {zbg: 0}, {zbh: 0}, {zbi: 0}, {zbj: 0}, + {zbk: 0}, {zbl: 0}, {zbm: 0}, {zbn: 0}, {zbo: 0}, {zbp: 0}, {zbq: 0}, {zbr: 0}, {zbs: 0}, {zbt: 0}, + {zca: 0}, {zcb: 0}, {zcc: 0}, {zcd: 0}, {zce: 0}, {zcf: 0}, {zcg: 0}, {zch: 0}, {zci: 0}, {zcj: 0}, + {zck: 0}, {zcl: 0}, {zcm: 0}, {zcn: 0}, {zco: 0}, {zcp: 0}, {zcq: 0}, {zcr: 0}, {zcs: 0}, {zct: 0}, + {zda: 0}, {zdb: 0}, {zdc: 0}, {zdd: 0}, {zde: 0}, {zdf: 0}, {zdg: 0}, {zdh: 0}, {zdi: 0}, {zdj: 0}, + {zdk: 0}, {zdl: 0}, {zdm: 0}, {zdn: 0}, {zdo: 0}, {zdp: 0}, {zdq: 0}, {zdr: 0}, {zds: 0}, {zdt: 0} +> diff --git a/test/two-hundred-xored-types/setup.ts b/test/two-hundred-xored-types/setup.ts new file mode 100644 index 0000000..fe18bfb --- /dev/null +++ b/test/two-hundred-xored-types/setup.ts @@ -0,0 +1,24 @@ +import type { XOR } from '../../src' + +export type XOR_200 = XOR< + {a: 0}, {b: 0}, {c: 0}, {d: 0}, {e: 0}, {f: 0}, {g: 0}, {h: 0}, {i: 0}, {j: 0}, + {k: 0}, {l: 0}, {m: 0}, {n: 0}, {o: 0}, {p: 0}, {q: 0}, {r: 0}, {s: 0}, {t: 0}, + {aa: 0}, {ab: 0}, {ac: 0}, {ad: 0}, {ae: 0}, {af: 0}, {ag: 0}, {ah: 0}, {ai: 0}, {aj: 0}, + {ak: 0}, {al: 0}, {am: 0}, {an: 0}, {ao: 0}, {ap: 0}, {aq: 0}, {ar: 0}, {as: 0}, {at: 0}, + {ba: 0}, {bb: 0}, {bc: 0}, {bd: 0}, {be: 0}, {bf: 0}, {bg: 0}, {bh: 0}, {bi: 0}, {bj: 0}, + {bk: 0}, {bl: 0}, {bm: 0}, {bn: 0}, {bo: 0}, {bp: 0}, {bq: 0}, {br: 0}, {bs: 0}, {bt: 0}, + {ca: 0}, {cb: 0}, {cc: 0}, {cd: 0}, {ce: 0}, {cf: 0}, {cg: 0}, {ch: 0}, {ci: 0}, {cj: 0}, + {ck: 0}, {cl: 0}, {cm: 0}, {cn: 0}, {co: 0}, {cp: 0}, {cq: 0}, {cr: 0}, {cs: 0}, {ct: 0}, + {da: 0}, {db: 0}, {dc: 0}, {dd: 0}, {de: 0}, {df: 0}, {dg: 0}, {dh: 0}, {di: 0}, {dj: 0}, + {dk: 0}, {dl: 0}, {dm: 0}, {dn: 0}, {do: 0}, {dp: 0}, {dq: 0}, {dr: 0}, {ds: 0}, {dt: 0}, + {za: 0}, {zb: 0}, {zc: 0}, {zd: 0}, {ze: 0}, {zf: 0}, {zg: 0}, {zh: 0}, {zi: 0}, {zj: 0}, + {zk: 0}, {zl: 0}, {zm: 0}, {zn: 0}, {zo: 0}, {zp: 0}, {zq: 0}, {zr: 0}, {zs: 0}, {zt: 0}, + {zaa: 0}, {zab: 0}, {zac: 0}, {zad: 0}, {zae: 0}, {zaf: 0}, {zag: 0}, {zah: 0}, {zai: 0}, {zaj: 0}, + {zak: 0}, {zal: 0}, {zam: 0}, {zan: 0}, {zao: 0}, {zap: 0}, {zaq: 0}, {zar: 0}, {zas: 0}, {zat: 0}, + {zba: 0}, {zbb: 0}, {zbc: 0}, {zbd: 0}, {zbe: 0}, {zbf: 0}, {zbg: 0}, {zbh: 0}, {zbi: 0}, {zbj: 0}, + {zbk: 0}, {zbl: 0}, {zbm: 0}, {zbn: 0}, {zbo: 0}, {zbp: 0}, {zbq: 0}, {zbr: 0}, {zbs: 0}, {zbt: 0}, + {zca: 0}, {zcb: 0}, {zcc: 0}, {zcd: 0}, {zce: 0}, {zcf: 0}, {zcg: 0}, {zch: 0}, {zci: 0}, {zcj: 0}, + {zck: 0}, {zcl: 0}, {zcm: 0}, {zcn: 0}, {zco: 0}, {zcp: 0}, {zcq: 0}, {zcr: 0}, {zcs: 0}, {zct: 0}, + {zda: 0}, {zdb: 0}, {zdc: 0}, {zdd: 0}, {zde: 0}, {zdf: 0}, {zdg: 0}, {zdh: 0}, {zdi: 0}, {zdj: 0}, + {zdk: 0}, {zdl: 0}, {zdm: 0}, {zdn: 0}, {zdo: 0}, {zdp: 0}, {zdq: 0}, {zdr: 0}, {zds: 0}, {zdt: 0} +>