π Search Terms
mapped conditional type keyof generic extends ternary
π Version & Regression Information
- This changed between versions 4.0.5 and 4.1.5
(Because the mapped type wouldn't work prior to 4.1)
β― Playground Link
https://www.typescriptlang.org/play/?ts=5.9.2#code/KYDwDg9gTgLgBDAnmYcCyBDMKAmAVCPKDAN2CgGdgcAePAPjgF4BYAKDjgG93POBtANJwAlgDs4Aa2CIIAMzh44GCoqEBdOKBjAxOVRjGI4AfjjCAXOfVWA5DGJlK1W7zgBfduyQo4ACQgnPAALEQoARmZ0LFwCIlJyKloeDmUjAAUoCDArQ0Q3CgdM7KtCqHEAczcIACMAK2KcuFq64ABjGHZ3enYAel64QBRyQHg-5QAbMbgwLJRYEWADKFQxCAB3OAAiBwTnHA2LPoGfVACg0IiolP6+TjzGqy3HROoNgG5Dm7gy+83tpyS3h8bi0fo8dgD3mxrp42N5kCdAuQQmEAEx0RhMaLYahxJ67GgpW4ZGa5IwFIokr4OSrVeo-PBdHpQgaAGXJmnSZqJVABbMIUSoHZkIeH+RFQZEUNEMS5Avh3Slg-4vSHXG7fBV-Z57FUDGFw3ynJHnADM6KimGx+EIeKSBLc8pKaXyqXVjrKNNSIMpACV2tBaNJZAo8AAaOBiACu3Jq5CZ3Q+bK92S5cF5FH5Ygqguux1FZzCpulmKuAxuDqaiq1gKFaopjsru2r0KAA
π» Code
export type MappedToTraversed<T> =
{
[K in keyof T as T[K] extends any ? K : K]: 'traversed'
}
type HoverThis1 = MappedToTraversed<{
anyProp: any
strProp: string
objProp: object
}>
// βοΈ all properties are now "traversed":
// type HoverThis1 = {
// anyProp: "traversed";
// strProp: "traversed";
// objProp: "traversed";
// }
type HoverThis2<T> = MappedToTraversed<{
anyProp: any
strProp: string
objProp: T
}>
// β objProp is missing:
// type HoverThis2<T> = {
// anyProp: "traversed";
// strProp: "traversed";
// }
type HoverThis3<T> = MappedToTraversed<{
anyProp: any
strProp: string
objProp: Record<keyof T, number>
}>
// β objProp is missing:
// type HoverThis3<T> = {
// anyProp: "traversed";
// strProp: "traversed";
// }
π Actual behavior
The objProp is missing from the HoverThis types when it is somehow using a generic (e.g. when used as property type or key in a Record). Looks like it is not being traversed during mapping at all due to the extends clause, because the ternary as T[K] extends any ? K : K should IMHO always evaluate to K.
π Expected behavior
objProp should be listed in all HoverThis types.
Additional information about the issue
I think it's due to the extends clause, because if the mapping is simply written as
export type MappedToTraversed<T> =
{
[K in keyof T as K]: 'traversed'
}
objProp is listed in the resulting HoverThis types.
It also fails if
- the ternary is the other way round, i.e.
any extends T[K] ? K : K
- the ternary checks something that should always be true
T[K] extends T[K] ? K : K
- I try to disable union distribution according to hand book:
[T[K]] extends [any] ? K : K
However, if I mess up disabling the union distribution (putting only one side in square brackets), it works..? [T[K]] extends any ? K : K. This feels like an unsafe workaround.
π Search Terms
mapped conditional type keyof generic extends ternary
π Version & Regression Information
(Because the mapped type wouldn't work prior to 4.1)
β― Playground Link
https://www.typescriptlang.org/play/?ts=5.9.2#code/KYDwDg9gTgLgBDAnmYcCyBDMKAmAVCPKDAN2CgGdgcAePAPjgF4BYAKDjgG93POBtANJwAlgDs4Aa2CIIAMzh44GCoqEBdOKBjAxOVRjGI4AfjjCAXOfVWA5DGJlK1W7zgBfduyQo4ACQgnPAALEQoARmZ0LFwCIlJyKloeDmUjAAUoCDArQ0Q3CgdM7KtCqHEAczcIACMAK2KcuFq64ABjGHZ3enYAel64QBRyQHg-5QAbMbgwLJRYEWADKFQxCAB3OAAiBwTnHA2LPoGfVACg0IiolP6+TjzGqy3HROoNgG5Dm7gy+83tpyS3h8bi0fo8dgD3mxrp42N5kCdAuQQmEAEx0RhMaLYahxJ67GgpW4ZGa5IwFIokr4OSrVeo-PBdHpQgaAGXJmnSZqJVABbMIUSoHZkIeH+RFQZEUNEMS5Avh3Slg-4vSHXG7fBV-Z57FUDGFw3ynJHnADM6KimGx+EIeKSBLc8pKaXyqXVjrKNNSIMpACV2tBaNJZAo8AAaOBiACu3Jq5CZ3Q+bK92S5cF5FH5Ygqguux1FZzCpulmKuAxuDqaiq1gKFaopjsru2r0KAA
π» Code
π Actual behavior
The
objPropis missing from theHoverThistypes when it is somehow using a generic (e.g. when used as property type or key in aRecord). Looks like it is not being traversed during mapping at all due to the extends clause, because the ternaryas T[K] extends any ? K : Kshould IMHO always evaluate toK.π Expected behavior
objPropshould be listed in allHoverThistypes.Additional information about the issue
I think it's due to the
extendsclause, because if the mapping is simply written asobjPropis listed in the resultingHoverThistypes.It also fails if
any extends T[K] ? K : KT[K] extends T[K] ? K : K[T[K]] extends [any] ? K : KHowever, if I mess up disabling the union distribution (putting only one side in square brackets), it works..?
[T[K]] extends any ? K : K. This feels like an unsafe workaround.