Why do subtypes need to be assigned to a variable before being used as a function argument?

一个人想着一个人 提交于 2021-01-27 18:26:58

问题


I'm learning about subtypes and am wondering why an example given here https://www.typescriptlang.org/docs/handbook/type-compatibility.html compiles, but when I pass the subtype directly as an argument to a function, it does not compile.

Here's the original code from typescriptlang.org

interface Named {
    name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: "Alice", location: "Seattle" };


function greet(n: Named) {
    console.log("Hello, " + n.name);
}
greet(y); // OK

That compiles fine. But this version, where the subtype is not assigned to y, fails.

interface Named {
    name: string;
}

let x: Named;

function greet(n: Named) {
    console.log("Hello, " + n.name);
}
greet({ name: "Alice", location: "Seattle" }); // NOT OK

I get the error:

Argument of type '{ name: string; location: string; }' is not assignable to parameter of type 'Named'. Object literal may only specify known properties, and 'location' does not exist in type 'Named'.

Why is it that the subtype { name: "Alice", location: "Seattle" } has to be assigned to a variable first?


回答1:


It's because when you use a "fresh" object literal (meaning one that hasn't been assigned to a variable yet) in a place that expects a particular type, it's often an error to add properties not mentioned in the type. So this is flagged as an error via excess property checking. It's one of the few places where a type is treated as "closed" or "exact" as opposed to "open".

There are workarounds in the case where you don't mean for excess property checks to happen. One is to add an index signature to the type of the n parameter so that all extra properties are acceptable:

function greet(n: Named & { [x: string]: unknown }) {
  console.log("Hello, " + n.name);
}
greet({ name: "Alice", location: "Seattle" }); // okay

Or, if you usually want such checking but just want to call greet() with that particular object literal, you can use a type assertion to avoid intermediate variables:

greet({ name: "Alice", location: "Seattle" } as Named); // okay

It's up to you. Okay, hope that helps; good luck!



来源:https://stackoverflow.com/questions/56007522/why-do-subtypes-need-to-be-assigned-to-a-variable-before-being-used-as-a-functio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!