【问题标题】:Create original type by adding fields to an Omit type combined with generics通过将字段添加到 Omit 类型并结合泛型来创建原始类型
【发布时间】:2021-06-27 07:25:14
【问题描述】:

在打字稿中,您可以通过添加使用Omit 删除字段来重新创建类型:

interface Animal {
  name: string
}

interface Dog extends Animal {
  goodboy: true
}

const makeDog = (name: string, attributes: Omit<Dog, 'name'>): Dog => ({
  ...attributes,
  name
})

但是,当您尝试使用泛型类型执行此操作时,它会失败并出现错误:

// Type 'Omit<T, "name"> & { name: string; }' is not assignable to type 'T'.
// 'Omit<T, "name"> & { name: string; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Animal'.
const makeAnimal = <T extends Animal>(name: string, attributes: Omit<T, 'name'>): T => ({
  ...attributes,
  name
})

有没有办法创建makeAnimal 函数?

Typescript playground

【问题讨论】:

    标签: typescript generics types


    【解决方案1】:

    这样做的原因是一般情况下不安全

    interface Animal {
      name: string
    }
    
    interface Dog extends Animal {
      goodboy: true
    }
    
    interface Cat extends Animal {
      name: 'cat'
    }
    
    const makeAnimal = <T extends Animal>(name: string, attributes: Omit<T, 'name'>): T => ({
      ...attributes,
      name
    })
    
    // This would make a Cat named 'Mittens', while the interface says a Cat is always named 'cat'
    const cat = makeAnimal<Cat>('Mittens', {})
    

    您需要从基本类型中显式选择,以便在调用站点上将其合并:

    const makeAnimal = <T extends Animal>(name: string, attributes: Omit<T, 'name'>): Omit<T, 'name'> & Pick<Animal, 'name'> => ({
      ...attributes,
      name
    })
    
    // OK
    const fluffy: Dog = makeAnimal<Dog>('Fluffy', { goodboy: true })
    
    // valid type error:
    // Type 'Omit<Cat, "name"> & Pick<Animal, "name">' is not assignable to type 'Cat'.
    // Types of property 'name' are incompatible.
    // Type 'string' is not assignable to type '"cat"'.
    const cat: Cat = makeAnimal<Cat>('Mittens', {})
    

    【讨论】:

    • 非常有趣 - 基于同样的事情我有一个半答案,但我可以解释为什么 Omit&lt;T, 'name'&gt; &amp; Pick&lt;Animal, 'name'&gt; 工作 - 很高兴发现!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多