Last active
May 8, 2025 07:08
-
-
Save BrandonStudio/ad611d95d8b4db8605ae0c4a6b25f26e to your computer and use it in GitHub Desktop.
Typescript typing issue with `extends` keyword
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type A = { | |
s: true; | |
i: {}; | |
}; | |
type B = { | |
s: true; | |
j: {}; | |
}; | |
type C = { | |
s: false; | |
i: {}; | |
}; | |
type D = { | |
s: false; | |
j: {}; | |
}; | |
type AC = A | C; | |
type BD = B | D; | |
type Conditional<T1, T2, B extends true | false> = B extends true ? T1 : T2; | |
function func1< | |
Bool extends true | false, | |
ABCD extends AC | BD, | |
AC_BD extends Bool extends true ? AC : BD, | |
>(b: Bool) { | |
type X = Extract<ABCD, { s: true }>; | |
// ABCD extends { s: true } ? ABCD : never | |
// Expected: A | B | |
type Y = Extract<AC_BD, { s: true }>; | |
// AC_BD extends { s: true } ? AC_BD : never | |
// Expected: Conditional<A, B, Bool> | |
function foo1(): ABCD { | |
return {} as ABCD; | |
} | |
function foo2(): AC_BD { | |
return {} as AC_BD; | |
} | |
const r1 = foo1(); | |
if (r1.s) { | |
const r1_ = r1; // ABCD. Expected: A | B | |
} else { | |
const r1_ = r1; // ABCD. Expected: C | D | |
} | |
const r2 = foo2(); | |
if (r2.s) { | |
const r2_ = r2; // AC_BD. Expected: Conditional<A, B, Bool> | |
} else { | |
const r2_ = r2; // AC_BD. Expected: Conditional<C, D, Bool> | |
} | |
} | |
function func2<Bool extends true | false>(b: Bool) { | |
type X = Extract<AC | BD, { s: true }>; // A | B. ✓ | |
type Y = Extract<Conditional<AC, BD, Bool>, { s: true }>; | |
// Conditional<AC, BD, Bool> extends { s: true; } ? { s: true; } & Conditional<AC, BD, Bool> : never | |
// Expected: Conditional<A, B, Bool> | |
function foo1(): AC | BD { | |
return {} as AC | BD; | |
} | |
function foo2(): Conditional<AC, BD, Bool> { | |
return {} as Conditional<AC, BD, Bool>; | |
} | |
const r1 = foo1(); | |
if (r1.s) { | |
const r1_ = r1; // A | B. ✓ | |
} else { | |
const r1_ = r1; // C | D. ✓ | |
} | |
const r2 = foo2(); | |
if (r2.s) { | |
const r2_ = r2; // Conditional<AC, BD, Bool>. Expected: Conditional<A, B, Bool> | |
} else { | |
const r2_ = r2; // Conditional<AC, BD, Bool>. Expected: Conditional<C, D, Bool> | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment