【问题标题】:How to assign a conditional value to a key based on another of its properties如何根据键的另一个属性为键分配条件值
【发布时间】:2021-11-23 06:31:05
【问题描述】:

我想知道如何为依赖于同一对象内另一个键的键分配值。在这种情况下,我想说如果动物有主人,它不是食物,但如果它没有主人,它就是食物。因此,在我的示例中,对象 animal 应评估为 true,而 animal2 应评估为 false,但它们不会。

> I have tried isFood: animal.owner ? false: true 
> I have tried isFood: animal.hasOwnProperty("owner") ? false: true
> I have tried isFood: "owner" in animal ? false: true
> I have tried isFood: this.owner ? false: true
interface personInterface {
    name: string,
    age: number,
    isMember: boolean
};
interface animalInterface<T> {
    owner?: T,
    sound: string,
    species: string,
    isFood: boolean
}

let person: personInterface;

person = {
    name: "justin",
    age: 30,
    isMember: true
}

let animal: animalInterface<personInterface>;
let animal2: animalInterface<personInterface>;

animal = {
    owner: {...person},
    sound: "Woof",
    species: "Dog",
    isFood: this.owner ? false: true
}

animal2 = {
    sound: "Woof",
    species: "Dog",
    isFood: this.owner ? false: true 
}

【问题讨论】:

    标签: javascript typescript javascript-objects


    【解决方案1】:

    this 可能因使用位置、函数内部或全局而异。为了引用当前对象并仍将键作为属性访问,您可以使用get 访问器,如下所示。您可以阅读有关get 访问器here 的更多信息。

    animal = {
        owner: { ...person },
        sound: "Woof",
        species: "Dog",
        get isFood() {
            // Here this refers to current object
            return this.owner ? false : true
        }
    }
    
    animal2 = {
        sound: "Woof",
        species: "Dog",
        get isFood() {
            return this.owner ? false : true
        }
    }
    
    console.log(animal.isFood);
    console.log(animal2.isFood);
    
    

    【讨论】:

      【解决方案2】:

      为了实现它,你需要使用discriminated unions

      interface PersonInterface {
          name: string,
          age: number,
          isMember: boolean
      };
      
      interface AnimalInterfaceBase<T> {
          owner?: T,
          sound: string,
          species: string,
          isFood: boolean
      }
      
      type WithOwner<T> = {
          owner: T,
          sound: string,
          species: string,
          isFood: false
      }
      
      type WithoutOwner = {
          sound: string,
          species: string,
          isFood: true
      }
      
      
      type AnimalInterface<T> = WithOwner<T> | WithoutOwner
      
      
      let person: PersonInterface;
      
      person = {
          name: "justin",
          age: 30,
          isMember: true
      }
      
      let animal: AnimalInterface<PersonInterface>;
      let animal2: AnimalInterface<PersonInterface>;
      
      animal = {
          owner: person,
          sound: "Woof",
          species: "Dog",
          isFood: false
      }
      
      animal2 = {
          owner: person, // expected error
          sound: "Woof",
          species: "Dog",
          isFood: true
      }
      

      Playground

      附:接口名称大写是惯例。

      【讨论】:

        【解决方案3】:

        在这种情况下,您可以使用标记的联合类型。基本上,您创建两个接口并通过属性识别它们,在您的情况下为isFood

        interface BaseAnimalInterface {
            sound: string;
            species: string;
            isFood: boolean;
        }
        
        interface AnimalInterface extends BaseAnimalInterface {
            isFood: true;
        }
        
        interface PetInterface<T = PersonInterface> extends BaseAnimalInterface {
            owner: T;
            isFood: false;
        }
        
        type AnimalType = AnimalInterface | PetInterface;
        

        然后,如果您在 if/switch 语句中检查该属性,您将获得正确的类型:

        function playSound(animal: AnimalType): void {
            if (animal.isFood) {
                // Casted automatically to `AnimalInterface`
            } else {
                // Casted automatically to `PetInterface`
            }
        }
        

        Full example.

        【讨论】:

          猜你喜欢
          • 2021-06-06
          • 1970-01-01
          • 2015-09-09
          • 2021-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-23
          • 1970-01-01
          相关资源
          最近更新 更多