【问题标题】:TypeScript Field Type Dependent on Other FieldTypeScript 字段类型依赖于其他字段
【发布时间】:2022-01-14 09:45:01
【问题描述】:
type Formula =
  | {
      fn: (a: number) => number;
      arg: number;
    }
  | {
      fn: (a: () => number) => number;
      arg: () => number;
    };

在此示例中,我如何键入公式,以便 fn 始终接受 arg 作为参数?我仍然需要像 Formula 这样的类型来表示这两种公式,以防我想将它们混合在一个列表中或创建一个可以返回任何一种类型的函数。

formula1.fn(formula1.arg) // should always work.

换句话说:

  1. 如果argnumber,则fn 应该是(number) => number
  2. 如果arg() => number,则fn 应该是(() => number) => number
  3. 存在一种涵盖两种类型的公式。
// Just applies formula.fn to formula.arg
const calc = (
  formula: Formula
) => formula.fn(formula.arg);  // formula.arg fails to type check

/*
Argument of type 'number | (() => number)' is not assignable to parameter of type 'number & (() => number)'.
Type 'number' is not assignable to type 'number & (() => number)'.
    Type 'number' is not assignable to type '() => number'.ts(2345)
*/


// Should succeed (fn takes a number and arg is a number)
const num1 = calc({
  fn: (a) => a + 1,
  arg: 3
})

// Should succeed (fn takes a () => number and arg is a () => number)
const num2 = calc({
  fn: (a) => a() + 1,
  arg: () => 3
})

// Should fail because arg is a number and fn expects a () => number parameter
const num3 = calc({
  fn: (a) => a() + 1,
  arg: 4
})

// Should fail because arg is a () => number and fn expects a number parameter
const num4 = calc({
  fn: (a) => a + 1,
  arg: () => 4
})

// It should be possible to build an array
// containing types of formulas.
const formulas: Formula = [
   // plain number formula
  {
    fn: a => a + 3,
    arg: 4
  },
   // () => number formula
  {
    fn: a => a() * 2,
    arg: () => 11
  }
]

const answers = formulas.map(calc)

谢谢!

【问题讨论】:

    标签: typescript types typescript-generics


    【解决方案1】:

    你需要一个泛型函数。

    type Formula = {
       fn: <T extends (() => number) | number>(a: T) => number;
    }
    

    或者,也许您更喜欢第二个:

    type Formula<Arg> = {
          fn: (a: Arg) => number;
          arg: Arg
    }
    
    const calc = <T extends (() => number) | number>(
      formula: Formula<T>
    ) => formula.fn(formula.arg);
    

    Read more about generic types here

    我的理解正确吗?

    【讨论】:

    • 这是一个很好的答案,只要 OP 不需要像原来的 Formula 这样的联合类型,比如 this,其中 calc() 拒绝 Formula&lt;()=&gt;number&gt; | Formula&lt;number&gt; 类型的参数.
    • 我想我遇到了这个问题。如果我想制作一个公式列表并全部计算它们(如this),我无法为列表分配类型。
    • @EugeneWolffe 如果您需要列表或其他用例,请edit 提出您的问题,以便minimal reproducible example 准确显示您遇到的问题,以便答案可以解决这些问题。我很乐意尝试做一些事情,但最好是在问题中列出了所有必要的用例之后。
    • @jcalz 我尝试澄清问题规范,同时保持最小化。您的示例准确地显示了我正在尝试做的事情,所以如果您有任何建议可以使问题更清楚,请告诉我。谢谢:)
    • 是否有类似this 的问题阻止 TypeScript 允许映射公式的混合列表?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 2021-09-21
    • 2016-06-18
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多