Typescript 1.8 introduced the string literal type. However, when passing in an object as a parameter as in the following:
const test = {
a: "hi",
b: "hi",
c: "hi"
};
interface ITest {
a: "hi" | "bye"
}
function testFunc (t: ITest) {
}
testFunc(test);
It fails with:
Argument of type '{ a: string; b: string; c: string; }' is not assignable to parameter of type 'ITest'. Types of property 'a' are incompatible. Type 'string' is not assignable to type '"hi" | "bye"'. Type 'string' is not assignable to type '"bye"'.
I would expect this to work since it meets the requirements of the interface, but I might be overlooking something.
The type of test.a
has been inferred as string
and not "hi"
. The compiler is comparing the types and not the initial string expression.
In order to make this work you need to type that property as "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);
Note that in the original case it wouldn't make sense for the compiler to infer the type of test.a
to be "hi"
because you can assign a different value to test.a
before it reaches testFunc(test)
—ex. test.a = "not hi"
.
Side note: It's good the compiler doesn't infer the type the be the string expression for even constant string variables. That would also lead to a lot of annoyances... imagine this:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With