网站搜索

类型推断 - TypeScript 从三元条件中推断字符串字面量


这是一个简化的例子:

function doSomething(animal: 'bird' | 'fish'){ }

let flies=true;

const animal = flies ? 'bird' : 'fish'

doSomething(animal);         

TypeScript 在从三元条件表达式给 animal 赋值时推断类型为 'bird' | 'fish'。(如果 animal 不是 const,它会报错,因为它会推断为 string 类型,而 string 类型不能赋值给 'bird' | 'fish')

但是

const parms ={
    animal: flies ? 'bird' : 'fish'
}
doSomething(parms);  /* Argument of type '{ animal: string; }' is not    
                        assignable to parameter of type '{ animal: "bird" | "fish"; } */

这里它从三元条件推断字符串。有没有办法保持这种风格(即不必定义类型并将字段 animal 声明为该类型)

答案#1

TypeScript 仅在某些情况下推断字符串字面量类型。一个属性通常不属于这些情况,除非有额外的情况提示该属性是字面量类型。(这与三元运算符无关)。

在 Typescript 3.4(撰写本文时尚未发布,但已经可以通过 npm 安装 typescript@next 获取)中,你将能够向编译器提示,你希望按照此问题推断对象字面量:

let flies=true;
//types as  { readonly animal: "bird" | "fish"; }
const parms ={
    animal: flies ? 'bird' : 'fish'
} as const

在 3.3 及以下版本中,你可以使用一个函数来告诉编译器你希望推断出字面量类型:

let flies=true;
function withLiteralTypes<T extends Record<string, P>, P extends string | number | null | boolean | Record<string, P>> (o: T) {
    return o;
}
// types as { animal: "bird" | "fish"; }
const parms =withLiteralTypes({
    animal: flies ? 'bird' : 'fish',
})