Машинопись выводить строковый литерал из троичного условного

Это упрощенный пример:

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

let flies=true;

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

doSomething(animal);         

Typescropt выводит тип "птица" | "Рыба" в отведении к животному из тройной условно. (если бы животное не было константным, оно жаловалось бы, так как выводило бы строку типа, которую нельзя присвоить '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"; } */

Здесь выводится строка из троичной условности. Есть ли способ сохранить вещи в этом стиле (то есть не нужно определять тип и объявлять полевое животное как этот тип)

1 ответ

Решение

Typescript выводит только строковые литеральные типы в определенной ситуации. Свойство, как правило, не является одним из таких случаев, если только нет дополнительных обстоятельств, чтобы намекнуть литеральный тип для свойства. (это не имеет ничего общего с троичным оператором).

В Typescript 3.4 (не выпущен на момент написания, но уже доступен как typescript@next в npm) вы сможете намекнуть компилятору, что вы хотите, чтобы объектные литералы были выведены в соответствии с этой проблемой:

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',
})
Другие вопросы по тегам