当前位置: 首页 > 知识库问答 >
问题:

基于实例属性值的类属性类型保护

何禄
2023-03-14

如何使类示例推断config类型基于动物类型实例值检查:

enum Animal {
  BIRD = 'bird',
  DOG = 'dog',
}

type Base = {
    id: number
}

// Object example
type Smth = Base &
  (
    | {
        animalType: Animal.BIRD;
        config: number;
      }
    | {
        animalType: Animal.DOG;
        config: string;
      }
  );

// type guards working
const smthObj: Smth = {
  id: 1,
  animalType: Animal.BIRD,
  config: 1
};

// should be error
const smthObj2: Smth = {
  id: 1,
  animalType: Animal.BIRD,
  config: 'x'
};

if (smthObj.animalType === Animal.BIRD) {
 smthObj.config = 1;
 smthObj.config = 'x'; // should be error
}

// How to make it work the same for class?

class myClass {
  id: number;
  animalType: Animal;
  // this should be based on Animal type
  // number for bird and string for dog
  config: number | string; 

   constructor(id: number, animalType: Animal, config: number | string) {
    this.id = id;
    this.animalType = animalType;
    this.config = config
  }
}

const smthClass: myClass = 1 as any

// I need to make only this check to work
if (smthClass.animalType === Animal.BIRD) {
 smthClass.config = 1;
 smthClass.config = 'x'; // should be error
}

打字沙盒。

共有2个答案

陈昊昊
2023-03-14

使用泛型。

enum Animal {
  BIRD = 'bird',
  DOG = 'dog',
}

class myClass<T extends Animal = Animal> {
  id: number;
  animalType: T;
  config: T extends Animal.BIRD ? number : T extends Animal.DOG ? string : never; // this should be based on Animal type

  constructor(id: number, animalType: T, config: T extends Animal.BIRD ? number : T extends Animal.DOG ? string : never) {
    this.id = id;
    this.animalType = animalType;
    this.config = config
  }
}

const birdClass = new myClass(1, Animal.BIRD, 1);

if (birdClass.animalType === Animal.BIRD) {
  birdClass.config = 1;
  birdClass.config = 'x'; // should be error
}

const dogClass = new myClass(1, Animal.DOG, 'x');

if (dogClass.animalType === Animal.DOG) {
  dogClass.config = 1; // should be error
  dogClass.config = 'x';
}

const smthClass: myClass<Animal.BIRD> = 1 as any;

if (smthClass.animalType === Animal.BIRD) {
  smthClass.config = 1;
  smthClass.config = 'x'; // should be error
}

// Type guard function example for any class
function isBirdClass(smth: myClass): smth is myClass<Animal.BIRD> {
  return smth.animalType === Animal.BIRD ? true : false
}

function isDogClass(smth: myClass): smth is myClass<Animal.DOG> {
  return smth.animalType === Animal.DOG ? true : false
}

const unknownClass: myClass = 1 as any;

if (isBirdClass(unknownClass)) {
  unknownClass.config = 1;
  unknownClass.config = 'x'; // should be error
}

if (isDogClass(unknownClass)){
  unknownClass.config = 1; // should be error 
  unknownClass.config = 'x'; 
}

在 TypeScript Playground 中看到它。

注意:

    使用泛型
  • ,您甚至不需要类型保护,因为泛型会自动捕获类型错误。
燕星鹏
2023-03-14

类参数应该是一个数据结构的一部分。

这种方法既安全又简单

enum Animal {
  BIRD = 'bird',
  DOG = 'dog',
}

type Base = {
  id: number
}

// Object example
type Smth = Base &
  (
    | {
      animalType: Animal.BIRD;
      config: number;
    }
    | {
      animalType: Animal.DOG;
      config: string;
    }
  );

// How to make it work the same for class?

class myClass {
  constructor(public props: Smth) {
    this.props = props;
  }
}

const smthClass: myClass = 1 as any

if (smthClass.props.animalType === Animal.BIRD) {
  smthClass.props.config = 1;
  smthClass.props.config = 'x'; // should be error
}

更新

enum Animal {
  BIRD = 'bird',
  DOG = 'dog',
}


// How to make it work the same for class?

type Either<R> = R extends Animal.DOG ? string : number;

class myClass<T extends Animal> {
  id: number;
  animalType: T;
  config: Either<T>

  constructor(id: number, animalType: T, config: Either<T>) {
    this.id = id;
    this.animalType = animalType;
    this.config = config
  }
}

const smthClass: myClass<Animal.BIRD> = 1 as any

if (smthClass.animalType === Animal.BIRD) {
  smthClass.config = 1;
  smthClass.config = 'x'; // should be error
}
 类似资料:
  • 由于Python是动态语言,根据类创建的实例可以任意绑定属性。 给实例绑定属性的方法是通过实例变量,或者通过self变量: class Student(object): def __init__(self, name): self.name = name s = Student('Bob') s.score = 90 但是,如果Student类本身需要绑定一个属性呢?可

  • 主要内容:类变量(类属性),实例变量(实例属性),局部变量无论是类属性还是类方法,都无法像普通变量或者函数那样,在类的外部直接使用它们。我们可以将类看做一个独立的空间,则类属性其实就是在类体中定义的变量,类方法是在类体中定义的函数。 前面章节提到过,在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性又可细分为以下 3 种类型: 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量; 类体中,所有函数内部:以“self.变量名”的方式定义的

  • 问题内容: 我是python的新手,了解到类属性就像C ++中的静态数据成员一样。但是,尝试以下代码后,我感到困惑: f2.a是否也等于5? 如果将a定义为列表而不是整数,则预期行为: 我研究了 Python:类和实例属性之间的区别,但是它不能回答我的问题。 谁能解释为什么会有所不同?谢谢 问题答案: 在第二个示例中,您没有做相同的事情。在第一个示例中,您要分配一个新值: 在第二个示例中,您只是在

  • 下表列出了 4 个常见的明星人物: 姓名 年龄 周润发 58 成龙 55 刘德华 53 周星驰 54 进行归纳总结: 这些人物具有较高的知名度,把这些人物归类为明星; 每个明星两个属性:姓名和年龄。明星这个群体具有一个属性:数量,在这张表格中,明星的数量是 4; 姓名和年龄等属性是用于描述具体的一个对象(例如:周润发),而人物的数量是用于描述明星这个类别。 如果使用面向对象技术对以上实体进行描述,

  • 您好,我正在建立一个动物园微服务,包括动物、员工、客户和价格表。我的动物微服务可以工作,但在我的员工微服务中,我遇到了一个错误,即没有为类型“EmployeeModel”找到属性“name”。在问这个问题之前,我已经在网上搜索了几个小时,还有一些类似的问题。我在模型中没有“名字”employee_name,我只是感到困惑,不知道如何修复它。任何指导/建议/信息将不胜感激:)第一次发布,所以我希望我

  • 因此,我试图编写一个油腻的脚本,并希望基于同一树中的span值来切换一个特定的div类。这将绑定到一个按钮操作。 我想出的最好的办法是... $('span[data-doc=“true”]').parent().parent().parent().parent().parent().parent().parent().parent().toggle(); 为了向上到达树并隐藏我想要的div类,我