简体   繁体   English

如何使用没有 switch 语句的对象映射来区分接口的联合?

[英]How can I discriminate a union of interfaces using an object map without switch statement?

I'm fairly new to advanced typescripts concepts so bear with me.我对高级打字稿概念还很陌生,所以请耐心等待。 I have a number of projects that use objects to map out react components by some common prop (eg _type).我有许多项目使用对象通过一些常见的道具(例如_type)来映射反应组件。

What I want to do is automatically return the correct type for the component resolved using these object maps, however I just receive a type of any when I try this.我想要做的是自动返回使用这些对象映射解析的组件的正确类型,但是当我尝试这个any我只收到一个类型。

Many posts online recommend using switch statement (example below).许多在线帖子建议使用 switch 语句(示例如下)。 Our company uses the object map pattern so I'd like to avoid using the switch statements if possible.我们公司使用对象映射模式,所以我想尽可能避免使用 switch 语句。 Thanks.谢谢。 For added context, this is our first react project using typescript (moving from javascript).为了增加上下文,这是我们第一个使用 typescript(从 javascript 迁移)的 react 项目。

// types
type AnimalType = 'cat' | 'dog'

interface Cat {
  _type: AnimalType
  name: string
  onMeow: () => void
}

interface Dog {
  _type: AnimalType
  name: string
  onBark: () => void
}
type Animal = Cat | Dog

type AnimalMap = {
  [property in Animal['_type']]
}
// THIS WORKS BUT WE DON'T WANT TO USE THIS
// resolving animal type via switch
const CatComponent = ({ _type, name, onMeow }: Cat) => <div>I'm a cat!</div>

const DogComponent = ({ _type, name, onBark }: Dog) => <div>I'm a dog!</div>

function resolveAnimal(_type: AnimalType): React.Component<Animal> {
  
  switch(_type) {
    case "dog": return DogComponent
    case "cat": return CatComponent
  }
  return animalMap[_type]
}

// THIS DOESN'T WORK, WE'D LOVE TO USE THIS!
// resolving animal type via object map

const animalMap: AnimalMap = {
  cat: CatComponent,
  dog: DogComponent,
}

function resolveAnimal(_type: AnimalType): React.Component<Animal> {
  return animalMap[_type]
}

function App() {
  const ResolvedAnimalComponent = resolveAnimal('dog')
  return <ResolvedAnimalComponent onBark={() => console.log('HE BARKED')} />
}

Remove the explicit notation of : AnimalMap so that the object declaration values are not widened - you want TypeScript to see删除: AnimalMap的显式表示法,这样对象声明值就不会变宽 - 您希望 TypeScript 看到

const animalMap: {
  cat: CatComponent,
  dog: DogComponent,
}

not不是

const animalMap: AnimalMap

(not only because your AnimalMap doesn't note the values - the components - but also because it doesn't tie the properties to their components) (不仅因为您的AnimalMap没有记录值 - 组件 - 还因为它没有将属性与其组件联系起来)

Use利用

const animalMap = {
    cat: CatComponent,
    dog: DogComponent,
}

function resolveAnimal<T extends keyof typeof animalMap>(_type: T) {
    return animalMap[_type]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM