admin管理员组

文章数量:1378769

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 inpatible. 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.

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 inpatible. 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.

Share Improve this question asked Apr 5, 2016 at 1:42 Alexander MattoniAlexander Mattoni 4558 silver badges21 bronze badges 2
  • a, b, and c are string type in test and the "hi" | "bye" type in your interface. – nullforce Commented Apr 5, 2016 at 1:46
  • That makes sense, even though it's a bit counter intuitive. Thanks. – Alexander Mattoni Commented Apr 5, 2016 at 1:51
Add a ment  | 

1 Answer 1

Reset to default 13

The type of test.a has been inferred as string and not "hi". The piler is paring 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 piler 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 piler 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

本文标签: javascriptTypescript string literal with ducktyped objectStack Overflow