Búsqueda de sitios web

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'
};