打字稿 - 为什么不能推断出这个字符串文字类型?

时间:2018-06-08 14:25:01

标签: typescript types literals

以下代码段未通过类型检查:

type TaskType = 'SIMPLE' | 'COMPLEX'

interface TaskDefinition {
    name: string,
    task: string,
    taskType: TaskType
};

const test: TaskDefinition = { 
    name: '',
    task: '',
    taskType: 'SIMPLE' // This is fine
};

const tasks : TaskDefinition[] = ["apples", "pears"].map(i => {
    return {
        name: i,
        task: i,
        taskType: 'SIMPLE' // This one is not
    };
})
  

{name:string;任务:字符串; taskType:string; } [] 不可分配   输入 TaskDefinition []。

Try it

尽管目标类型为taskType

,但似乎string被推断为TaskType而不是TaskDefinition

造成这种情况的原因是什么?如何解决?

3 个答案:

答案 0 :(得分:8)

只有在将字符串文字类型分配给const时,它才会推断字符串文字类型。在创建对象文字时,编译器将推断string字符串常量而不是字符串文字类型。如果将对象文字直接分配给需要字符串文字类型的东西,那就没问题,因为在这种情况下,编译器只检查字符串常量是否可赋值给字符串文字类型。

这里的简单解决方案是指定map的类型参数,这仍将保留对map的返回值的编译器检查:

const tasks = ["apples", "pears"].map<TaskDefinition>(i => {
    return {
        name: i,
        task: i,
        taskType: 'SIMPLE'
    };
})

或者在字符串上使用类型断言到期望的字符串文字类型:

const tasks:TaskDefinition[] = ["apples", "pears"].map(i => {
    return {
        name: i,
        task: i,
        taskType: 'SIMPLE' as 'SIMPLE'
    };
}) 

您也可以直接在返回值上键入assert,但这会禁用对返回值的一些检查:

const tasks:TaskDefinition[] = ["apples", "pears"].map(i => {
    return <TaskDefinition>{
        wrongValue: "", // no error since we are asserting
        name: i,
        task: i,
        taskType: 'SIMPLE'
    };
}) 

答案 1 :(得分:3)

的原因

编译器没有将'SIMPLE'从字符串缩小到TaskType,因此您需要使用类型断言来帮助它。有两种选择。

在Object

处键入Assertion
const tasks: TaskDefinition[] = ["apples", "pears"].map(i => {
    return <TaskDefinition> {
        name: i,
        task: i,
        taskType: 'SIMPLE' // This one is not
    };
});

在值

处键入断言
const tasks: TaskDefinition[] = ["apples", "pears"].map(i => {
    return {
        name: i,
        task: i,
        taskType: <TaskType>'SIMPLE' // This one is not
    };
});

答案 2 :(得分:2)

我看到了解决这个问题的三种方法:

return {
        name: i,
        task: i,
        taskType: 'SIMPLE'
    } as TaskDefinition;

或者:

const tasks: TaskDefinition[] = ["apples", "pears"].map(i => {
    return {
        name: i,
        task: i,
        taskType: 'SIMPLE'
    };
}) as TaskDefinition[];

或者:

const tasks: TaskDefinition[] = ["apples", "pears"].map(i => {
    return {
        name: i,
        task: i,
        taskType: 'SIMPLE' as TaskType
    };
});

至于为什么,我不完全确定。为什么不使用字符串枚举代替自定义字符串类型?