typescript - 根据参数从映射类型返回类型

标签 typescript typescript-generics

我试图根据参数从泛型函数返回映射类型的值,该类型似乎在调用时被正确检测到,但在返回时报告错误。

我不考虑在 genericFunction 上使用重载,因为 E 在我的用例中可能有超过 100 个值。

enum E {
  e1="e1",
  e2="e2"
}

interface E1Payload {
  payloadFrom1: string
  anotherField: number
}

interface E2Payload {
  payloadFrom2: string
}

type Mapping = {
  [E.e1]: E1Payload
  [E.e2]: E2Payload
}

function genericFunction<K extends keyof Mapping>(e: K): Mapping[K] {
  if (e === E.e1) {
    // ERROR: Type '{ payloadFrom1: string; anotherField: number; }' is not assignable to type 'Mapping[K]'.
    // Type '{ payloadFrom1: string; anotherField: number; }' is not assignable to type 'E1Payload & E2Payload'.
    // Property 'payloadFrom2' is missing in type '{ payloadFrom1: string; anotherField: number; }' but required in type 'E2Payload'.
    return {
      payloadFrom1: "e1",
      anotherField: 2
    }
  }
  // ERROR: Type '{ payloadFrom2: string; }' is not assignable to type 'Mapping[K]'.
  // Type '{ payloadFrom2: string; }' is not assignable to type 'E1Payload & E2Payload'.
  // Type '{ payloadFrom2: string; }' is missing the following properties from type 'E1Payload': payloadFrom1, anotherField
  return {
    payloadFrom2: "e2"
  }
}

// This work correctly
const payloadE1: E1Payload = genericFunction(E.e1)
const payloadE2: E2Payload = genericFunction(E.e2)

Playground

最佳答案

您可以通过重写 genericFunction 以包含类似 map 的结构来解决此问题:

function genericFunction<K extends keyof Mapping>(e: K): Mapping[K] {
  return {
    [E.e1]: {
      payloadFrom1: "e1",
      anotherField: 2
    },
    [E.e2]: {
      payloadFrom2: "e2"
    }
  }[e]
}

对于更复杂的场景,我建议使用类型断言。 TypeScript 无法真正缩小泛型类型的范围。这就是为什么它无法理解您在这里所做的 if/else 缩小范围。

Playground

关于typescript - 根据参数从映射类型返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72969897/

相关文章:

javascript - 在 D3 Hierarchy Typescript 中,每个父子对具有相同的颜色

angular - Ionic Firebase Promise,每次更改值时调用一个函数

typescript - 我可以在泛型中使用命名 TS 类型,就像在 JS 中使用命名参数一样吗?

reactjs - 有没有办法提取 JSX 元素的 Prop 类型?

angular - 类型 'Observable<DocumentData[]>' 不可分配

node.js - 输入goose + Nestjs + mongodb : index not creating using @index decorator

reactjs - 使用 typescript 在 create-react-app 中加载 sass

typescript 可选的通用属性

typescript - 如何将 Typescript 函数重载与具有多个参数的函数一起使用?

javascript - TypeScript 无法缩小类型