TypeScript不同接口类型变量传入函数的类型兼容疑问
Car type variable to a function expecting Fruit? Great question! This boils down to TypeScript's structural type system—a core design choice that sets it apart from languages like Java or C# which use nominal type systems.
Let me break it down simply:
- In a nominal type system, compatibility depends on the name of the type. Even if two types have identical properties, if their names are different, they’re not considered compatible.
- In TypeScript’s structural system, compatibility is based on the actual shape/structure of the type. If one type has all the properties (with matching types) that another type requires, it’s deemed compatible—no matter what the type is named.
In your specific example:
- The
Fruitinterface only requires aname: stringproperty. - Your
Carinterface has that exactname: stringproperty, plus an extrawheels: numberproperty.
Since the fruitOnly function only ever accesses the name property of its parameter, a Car instance is perfectly safe to pass in—it has everything the function needs to run correctly. TypeScript recognizes this safety and doesn’t throw an error.
Here’s your code again to make this concrete:
interface Fruit { name: string } interface Car { name: string, wheels: number } function fruitOnly( paramFruit: Fruit ): void { console.log( paramFruit.name + " is a fruit!" ); } const myCar: Car = { name: "Tesla", wheels: 4 }; fruitOnly(myCar); // No error—Car has all the properties Fruit requires
This design is intentional: it makes TypeScript incredibly flexible. For example, if you’re using a third-party function that only needs an object with a name property, you can pass in any of your own types that include that property without writing extra type conversions or wrappers.
If you do want to enforce that only Fruit types (and not compatible shapes like Car) are allowed, you can add a unique "brand" property to the Fruit interface to make its structure distinct:
interface Fruit { name: string; _isFruit: never; // Unique marker property to distinguish Fruit from other types } interface Car { name: string; wheels: number; } const myCar: Car = { name: "Tesla", wheels: 4 }; fruitOnly(myCar); // Now this throws an error—Car lacks the _isFruit property
内容的提问来源于stack exchange,提问作者Ben

