代码之家  ›  专栏  ›  技术社区  ›  JC Ford

是否可以让函数接受类实例,但不接受纯对象?

  •  1
  • JC Ford  · 技术社区  · 5 年前

    我想编写一个函数,它将作为参数类实例,但不允许使用普通的匿名类型对象。

    例如:

    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
    
    1 回复  |  直到 5 年前
        1
  •  5
  •   Shaun Luttin    5 年前

    是否可以让函数接受类实例,但不接受纯对象?

    这目前是不可能的,因为typescript使用结构子类型。这意味着,当使用类构造函数创建的对象都具有兼容的属性时,它与普通的旧javascript对象文本兼容。

    这是医生说的 about type compatibility :

    TypeScripts结构类型系统的基本规则是,如果Y至少与X具有相同的成员,则X与Y兼容。若要检查Y是否可以分配给X,编译器将检查X的每个属性,以在Y中找到相应的兼容属性… 检查函数调用参数时使用相同的赋值规则。 [增加了empahsis]

    您的问题提出了一个问题:为什么要让函数接受类实例并拒绝普通的旧javascript对象?

        2
  •  1
  •   Vahid    5 年前

    您可以使用管道允许不同类型作为函数的参数。

    function pat(pet: Cat | Dog) {
        document.write(pet.name);
    }
    
        3
  •  1
  •   Ramesh Thiruchelvam    5 年前

    我建议您定义一个接口并使用它限制输入参数类型。这样你也有类型安全。此外,还可以强制参数类所需的内容。

    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
    
        4
  •  1
  •   Adrian Brand    5 年前

    为什么不为模型对象使用基接口、类和构造函数不是首选的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);