typescript infer string literal from ternary conditional

大憨熊 提交于 2019-12-11 04:10:55

问题


This is a simplified example:

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

let flies=true;

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

doSomething(animal);         

Typescropt infers type 'bird' | 'fish' in the assignation to animal from the ternary conditional. (if animal weren't const it would complain as it would infer type string not being assignable to 'bird' | 'fish')

But

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

Here it's infering string from the ternary conditional. Is there a way to keep things in this style (ie. not having to define a type and declaring the field animal as that type)


回答1:


Typescript only infers string literal types in certain situation. A property is unusually not one of those cases unless there are extra circumstances to hint a literal type for the property. (it has nothing to do with the ternary operator).

In Typescript 3.4 (unreleased at the time of writing, but already available as typescript@next in npm) you will be able to hint the compiler that you want object literals inferred as per this issue:

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

In 3.3 and below you could use a function to tell the compiler you want a literal type inferred:

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',
})


来源:https://stackoverflow.com/questions/54479507/typescript-infer-string-literal-from-ternary-conditional

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!