网站搜索

TypeScript 中的非破坏性类型断言


我正在寻找一种在 TypeScript 中将字面值约束为某种类型而不丢失推断类型信息的好方法。

让我们考虑一种保证有名称的类型 Named。

type Named = {
  name: string
};

使用类型注解会导致在用于定义 const cat1 的字面量中出现额外字段 born 时产生错误。

const cat1: Named = {
  name: 'Findus',
  born: 1984,  // this is an error
};
const name1 = cat1.name;
const born1 = cat1.born;  // this is an error

通过使用类型转换,我可以定义常量cat2,但它会丢失字段born的类型信息,这在之后尝试访问该字段时会产生问题。

const cat2 = {
  name: 'Findus',
  born: 1984,
} as Named;
const name2 = cat2.name;
const born2 = cat2.born;  // this is an error

解决这个问题的一种方法是在定义常量 cat3 时使用 IIFE 对字面量进行类型检查。

const cat3 = (<C extends Named>(c: C) => c)({
  name: 'Findus',
  born: 1984,
});
const name3 = cat3.name;
const born3 = cat3.born;

这是进行约束的预期方式吗,还是有更好的方法来编写兼容的代码?

答案#1

只需说你的类型是一个具有一个必需参数 name 的记录

interface Named extends Record<string, any> {
    name: string
}

或者你可以使用类似这样的东西

type Named<T> = T & {
    name: string
}


const a: Named<{ surname: string } > = {
    name: 'hello',
    surname: 'world'
};