Aserciones de tipo no destructivas en TypeScript
Estoy buscando una buena manera de restringir un valor literal en TypeScript a un cierto tipo sin perder la información de tipo inferida.
Consideremos un tipo Named que está garantizado a tener un nombre.
type Named = {
name: string
};
Usar una anotación de tipo crea un error para el campo extra born en el literal usado para definir la constante cat1.
const cat1: Named = {
name: 'Findus',
born: 1984, // this is an error
};
const name1 = cat1.name;
const born1 = cat1.born; // this is an error
Al usar un typecast puedo definir la constante cat2, pero pierde información de tipo para el campo born, lo que crea un problema al intentar acceder a ese campo más adelante.
const cat2 = {
name: 'Findus',
born: 1984,
} as Named;
const name2 = cat2.name;
const born2 = cat2.born; // this is an error
Una forma de resolver el problema es usar una IIFE para verificar el tipo del literal mientras se define la constante cat3.
const cat3 = (<C extends Named>(c: C) => c)({
name: 'Findus',
born: 1984,
});
const name3 = cat3.name;
const born3 = cat3.born;
¿Es esta la manera prevista de hacer la restricción, o hay mejores formas alternativas de escribir código compatible?
Respuesta #1
Simplemente di que tu tipo es un registro con un parámetro obligatorio name
interface Named extends Record<string, any> {
name: string
}
O puedes usar algo como esto
type Named<T> = T & {
name: string
}
const a: Named<{ surname: string } > = {
name: 'hello',
surname: 'world'
};
