Typescript строковый литерал с утиным типом объекта

Typescript 1.8 введен тип строкового литерала. Однако при передаче объекта в качестве параметра, как в следующем:

const test = {
    a: "hi",
    b: "hi",
    c: "hi"
};

interface ITest {
    a: "hi" | "bye"
}

function testFunc (t: ITest) {

}

testFunc(test);

Сбой:

Аргумент типа '{a: string; b: строка; c: string; } 'не присваивается параметру типа "ITest".   Типы собственности "а" несовместимы.     Тип 'string' не присваивается типу 'hi' | "пока" '.       Тип 'string' не присваивается типу '' bye ''.

Я ожидаю, что это сработает, так как оно отвечает требованиям интерфейса, но я мог бы что-то игнорировать.

Ответ 1

Тип test.a был выведен как string, а не "hi". Компилятор сравнивает типы, а не исходное строковое выражение.

Чтобы выполнить эту работу, вам нужно ввести это свойство как "hi" | "bye":

type HiBye = "hi" | "bye";

const test = {
    a: "hi" as HiBye,
    b: "hi",
    c: "hi"
};

interface ITest {
    a: HiBye
}

function testFunc (t: ITest) {
}

testFunc(test);

Обратите внимание, что в исходном случае для компилятора не имеет смысла выводить тип test.a как "hi", потому что вы можете назначить другое значение test.a до того, как оно достигнет testFunc(test) -ex, test.a = "not hi".

Боковое примечание: хорошо, что компилятор не выводит тип, являющийся строковым выражением для даже постоянных строковых переменных. Это также привело бы к множеству неприятностей... представьте себе это:

const myVariableTypedAsHi = "hi";   // implicitly typed as "hi"
let otherVar = myVariableTypedAsHi; // otherVar implicitly typed as "hi"

otherVar = "test"; // error: cannot assign `"test"` to `"hi"`—well that would be annoying