rid
rid

Reputation: 63442

Interface type inference

I have the following types:

interface A { a: string }
interface B extends A { b: string }
interface C extends A { c: string }

I now want to write the following function that returns an A:

function test(t: number): A {
    return t > 10
        ? { a: "a", b: "b" }
        : { a: "a", c: "c" };
}

This only works if I explicitly cast the returned objects to A, B or C, or if I create separate functions that explicitly return either a B or a C and use these to construct the object.

Is there any way the compiler can infer that the returned object is, in fact, a B or a C and therefore also an A, without me having to specify that?

Upvotes: 2

Views: 216

Answers (2)

rid
rid

Reputation: 63442

Looks like TypeScript does not infer the type of an object to be that defined by an interface.

The inferred type of { a: "a", b: "b" } is { a: string, b: string }, which can be used wherever an A or a B can be used, but it's neither A nor B, it's a different type.

So the answer is: no, the compiler will not infer A or B, it will infer something else, and a cast is necessary if the desired type is A or B.

Upvotes: 0

cartant
cartant

Reputation: 58400

My understanding is that it's because TypeScript enforces additional constraints upon object literals regarding excess properties. If it's re-written like this, there is no error:

interface A { a: string }
interface B extends A { b: string }

function test(): A {
    const result = { a: "a", b: "b" };
    return result;
}

There is also the suppressExcessPropertyErrors compiler option.

Upvotes: 1

Related Questions