typescript - ¿Cómo puedo acceder a una propiedad común de tipos de objetos anidados que a su vez se acceden con parámetros de tipo genérico?
A continuación hay un tipo genérico simple, "GetA", que se supone que simplemente indexa un objeto de tipo para obtener un tipo anidado; utiliza parámetros genéricos como dos de los índices. Sin embargo, en el último índice no genérico, lanza un error de tipo ("a" no se puede usar para indexar...), aunque todos los objetos posibles tengan la clave indexada. Espero que alguien pueda ayudarme a comprenderlo.
¿Cómo puedo hacer una versión funcional de GetA que use los mismos o similares parámetros?
type GetA<
T extends keyof TestObj,
P extends keyof TestObj[T]
> = TestObj[T][P]["a"];
// Type '"a"' cannot be used to index type 'TestObj[T][P]'.ts(2536)
type TestObj = {
nested1: {
prop: {
a: "foo1";
b: "bar1";
};
anotherProp: {
a: "foo2";
b: "bar2"
}
};
nested2: {
prop: {
a: "foo3";
b: "bar3";
};
};
};
Respuesta #1
Tenga en cuenta que extends no significa equal. Vea este ejemplo:
type GetA<
T extends keyof TestObj,
P extends keyof TestObj[T]
> = TestObj[T][P]['a'] // expected error
type TestObj = {
nested1: {
prop: {
a: "foo1";
b: "bar1";
};
anotherProp: {
a: "foo2";
b: "bar2"
}
};
nested2: {
prop: {
a: "foo3";
b: "bar3";
};
};
};
type Result = GetA<'nested1', 'prop' & { tag: 2 }> // unknown
Puedes encontrar más explicación en mi artículo
'prop' & { tag: 2 } se puede asignar a keyof TestObj[T] y al mismo tiempo es un subtipo de prop.
Intenta deshacerte de {tag: 2} y obtendrás el resultado esperado:
type Result = GetA<'nested1', 'prop'> // foo1
Por lo tanto, para hacerlo más seguro, necesitas agregar un tipo condicional:
type GetA<
T extends keyof TestObj,
P extends keyof TestObj[T]
> = 'a' extends keyof TestObj[T][P] ? TestObj[T][P]['a'] : never
type TestObj = {
nested1: {
prop: {
a: "foo1";
b: "bar1";
};
anotherProp: {
a: "foo2";
b: "bar2"
}
};
nested2: {
prop: {
a: "foo3";
b: "bar3";
};
};
};
type Result = GetA<'nested1', 'prop'> // foo1
Patio de recreo
Además, puedes hacerlo menos verboso:
type GetA<
T extends keyof TestObj,
P extends keyof TestObj[T],
Result = TestObj[T][P]
> = Result['a' & keyof Result]
