打字稿使第二个参数类型取决于第一个参数类型

时间:2021-05-21 10:31:33

标签: javascript typescript

nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://origin-site.com"

第一个参数a是一个枚举(Channel)值

如果参数a是github,则b的类型是GitHub

如果参数a是gitlab,那么b的类型是Gitlab

如何定义函数foo的类型?

2 个答案:

答案 0 :(得分:3)

使用conditional types technique。查看下面的示例或访问在线 playground 以进行实际测试(感谢对 Joonas 的帮助)

enum Channel {
  GITHUG = 'github',
  GITLAB = 'gitlab',
}

interface Github {
  _foo: number
}

interface Gitlab {
  _bar: number
}

type ParamType<C> = C extends Channel.GITHUG ? Github : Gitlab;
function foo<C extends Channel>(a: C, b: ParamType<C>): void {}

foo(Channel.GITLAB, { _foo: 1 }); // error
foo(Channel.GITLAB, { _bar: 1 }); // success

enter image description here


请让我知道它是否有效)

答案 1 :(得分:0)

这里有一些替代方法:

enum Channel {
  GITHUB = 'github',
  GITLAB = 'gitlab',
}

interface Github {
  type: 'Github'
}

interface Gitlab {
  type: 'Gitlab'
}

/**
 * First approach
 */
type Params = [Channel.GITHUB, Github] | [Channel.GITLAB, Gitlab]

function foo(...args: Params) {
  if (args[0] === Channel.GITHUB) {
    const x = args[1] // Github
  }
}


type Overloading =
  & ((a: Channel.GITHUB, b: Github) => void)
  & ((a: Channel.GITLAB, b: Gitlab) => void)


/**
 * Second approach
 */

const foo2: Overloading = (a: Channel, b: Github | Gitlab) => null as any

const result = foo2(Channel.GITHUB, { type: 'Github' }) // ok


/**
 * Third approach
 */
function foo3(a: Channel.GITLAB, b: Gitlab): void
function foo3(a: Channel.GITHUB, b: Github): void
function foo3(a: Channel, b: Github | Gitlab) {

}
foo3(Channel.GITLAB, { type: 'Gitlab' }) // ok

Playground