最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does TypeScript not throw an error when the function argument type is mismatched? - Stack Overflow

programmeradmin0浏览0评论

Here's a very basic example to demonstrate what I mean:

type Payload = {
    id: number;
}

type GreatPayload = {
    id: number;
    surprise: 4;
}

type Action = (payload: Payload) => void;

const action: Action = payload => null;

const payload: GreatPayload = {
    id: 1,
    surprise: 4,
};

action({ id: 1, surprise: 4 }); // <== as expected, this errors out because `surprise` is not present in `Payload`

action(payload); // <== my question is, why does this not throw an error?

(And the TypeScript playground link for an editable example.)

Why does action(payload) not throw an error when the type of payload that's passed in (GreatPayload) is clearly a mismatch for the function argument type Payload?

Here's a very basic example to demonstrate what I mean:

type Payload = {
    id: number;
}

type GreatPayload = {
    id: number;
    surprise: 4;
}

type Action = (payload: Payload) => void;

const action: Action = payload => null;

const payload: GreatPayload = {
    id: 1,
    surprise: 4,
};

action({ id: 1, surprise: 4 }); // <== as expected, this errors out because `surprise` is not present in `Payload`

action(payload); // <== my question is, why does this not throw an error?

(And the TypeScript playground link for an editable example.)

Why does action(payload) not throw an error when the type of payload that's passed in (GreatPayload) is clearly a mismatch for the function argument type Payload?

Share Improve this question asked May 16, 2020 at 18:28 Baggio WongBaggio Wong 5875 silver badges10 bronze badges 1
  • Possible duplicate of Typescript: prevent assignment of object with more properties than is specified in target interface – jcalz Commented May 16, 2020 at 23:55
Add a ment  | 

2 Answers 2

Reset to default 10

Object types in TypeScript are open/extendible, not closed/exact. That means it's acceptable for an object of type X to contain more properties than the definition of X mentions. You can think of object type definitions as describing the known properties of the type, while having no implications about possible unknown properties.

This openness is important because it allows interface extension and class inheritance. Your type definitions are nearly identical to

interface Payload {
    id: number;
}

interface GreatPayload extends Payload {
    surprise: 4;
}

And here you can see that GreatPayload is a special type of Payload. It has an extra property, but it's still a Payload. Same thing with class inheritance:

class Foo {
    a = "foo";
}
class Bar extends Foo {
    b = "bar";
}

A Bar instance is a Foo:

const f: Foo = new Bar(); // okay

The only place where the TypeScript piler treats object types as if they were exact is when you create a brand new object literal and assign it to a type. This is documented in the TypeScript Handbook as "Excess Property Checks"... and you can also look at microsoft/TypeScript#3755, the GitHub issue that discusses the need for this behavior; misspelling optional properties would be pletely uncaught errors without some sort of key checking like this. But it's not a full implementation of exact types.


So when you call this:

action({ id: 1, surprise: 4 });  // error

you are passing in a fresh object literal that contains an unexpected surprise property, and the piler warns via excess property checks. But when you call this:

action(payload);  // okay

you are passing in the variable payload, which is not an object literal itself, and the object literal you assigned to payload is no longer "fresh". So no excess property checks happen and you get no warning.


If you really want to see exact types implemented so that you could easily ask for Exact<Payload>, you might want to go to microsoft/TypeScript#12936 and give it a

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论