我想编写一个将类实例作为参数的函数,但不允许使用普通的匿名类型的对象。
例如:
class Dog {
constructor(name: string, breed: "husky" | "boxer") {
this.name = name;
this.breed = breed;
}
name: string;
breed: "husky" | "boxer";
}
class Cat {
constructor(name: string, breed: "siamese" | "persian") {
this.name = name;
this.breed = breed;
}
name: string;
breed: "siamese" | "persian";
}
function pat(pet: NoPlainObjects) {
document.write(pet.constructor.name);
}
pat(new Dog('Fido', 'boxer')); //works
pat(new Cat('Spot', 'persian')); //works
pat({name: 'snuffaluffagus'}); //compile error
答案 0 :(得分:5)
是否可以使一个函数接受类实例,但不接受普通对象?
当前不可能,因为TypeScript使用结构子类型。这意味着用类构造函数创建的对象在具有兼容属性的情况下与普通的旧JavaScript对象文字兼容。
TypeScript的结构类型系统的基本规则是,如果y与x至少具有相同的成员,则x与y兼容。为了检查是否可以将y赋给x,编译器会检查x的每个属性以在y中找到对应的兼容属性。检查函数调用参数时,使用相同的分配规则。 [empahsis添加]
您的问题提出了一个问题:为什么要让函数接受类实例并拒绝普通的旧JavaScript对象?
答案 1 :(得分:1)
您可以使用管道允许不同的类型作为函数的参数。
function pat(pet: Cat | Dog) {
document.write(pet.name);
}
答案 2 :(得分:1)
为什么不使用基本接口,模型对象的类和构造函数不是首选的TypeScript方法。
interface Pet {
name: string;
}
interface Dog extends Pet {
// no need to repeat name property.
breed: "husky" | "boxer";
}
function pat(pet: Pet) {
document.write(pet.name);
}
const fido: Dog = { name: 'Fido', breed: 'boxer' };
pat(fido);
答案 3 :(得分:1)
我建议您定义一个接口并使用该接口限制输入参数的类型。这样,您还具有类型安全性。另外,您可以强制执行参数类所需的内容。
interface Animal { name: string, breed: string };
class Dog implements Animal {
constructor(name: string, breed: "husky" | "boxer") {
this.name = name;
this.breed = breed;
}
name: string;
breed: "husky" | "boxer";
}
class Cat implements Animal {
constructor(name: string, breed: "siamese" | "persian") {
this.name = name;
this.breed = breed;
}
name: string;
breed: "siamese" | "persian";
}
function pat(pet: Animal) {
document.write(pet.name);
}
pat(new Dog('Fido', 'boxer')); //works
pat(new Cat('Spot', 'persian')); //works
pat({name: 'snuffaluffagus'}); //compile error