Typescript - Почему этот тип строкового литерала не может быть выведен? - PullRequest
0 голосов
/ 08 июня 2018

Следующий фрагмент не проходит проверку типа:

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 [].

Попробуйте

Кажется, что taskType выводится как string вместо TaskType, несмотря на то, что целевым типом является TaskDefinition

Что является причиной этого и как я могу это исправить?

Ответы [ 3 ]

0 голосов
/ 08 июня 2018

Причина

Компилятор не сужает 'SIMPLE' от строки к TaskType, поэтому вам нужно помочь ему с утверждением типа.Для этого есть два варианта.

Утверждение типа на объекте

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
    };
});
0 голосов
/ 08 июня 2018

Я вижу три способа исправить это:

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
    };
});

Почему я неполностью уверен.Почему бы не использовать строковые перечисления вместо пользовательского строкового типа?

0 голосов
/ 08 июня 2018

Typescript будет выводить строковые литеральные типы только тогда, когда вы присваиваете его 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'
    };
}) 

Редактировать Начиная с машинописного текста 3.4 ( PR ), вы также можете использовать утверждение as const для получения строкового литерала типа:

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

Конец редактирования

Вы также можете ввести assert непосредственно в возвращаемое значение, но это отключит некоторые проверки возвращаемого значения:

const tasks:TaskDefinition[] = ["apples", "pears"].map(i => {
    return <TaskDefinition>{
        wrongValue: "", // no error since we are asserting
        name: i,
        task: i,
        taskType: 'SIMPLE'
    };
}) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...