繁体   English   中英

创建 function 类型,其中返回类型取决于可选参数的存在

[英]Creating a function type where the return type depends on the existence of an optional parameter

考虑以下 JS function 和示例用法:

const fooInteractor = function(state, foo) {
  if (foo) {
    return {...state, foo}
  } else {
    return state.foo
  }
}

const state = {foo: 'foo', other: 'data'};
fooInteractor(state); // returns 'foo'
fooInteractor(state, 'bar'); // return {foo: 'bar', other: 'data'}

// we pass this function around generically and use it to interact with state
function interacts(state, interactorFn) {
  // ie interactorFn(state);
}

interacts(state, fooInteractor);

我怎样才能在 TS 土地上输入这个?

我可以定义一个类型并与 Typescript 满意的类型交互:

type StateInteractor {
  (state: State): string
  (state: State, value: string): State
}
function interact(state: State, stateFn: StateInteractor) {
  const data: string = stateFn(state);
  const changedState: State = stateFn(state, data);
  // etc
}

但是,在实际实施StateInteractor时,我遇到了问题:

const fooInteractor: StateInteractor = function(state: State, foo?: string) {
  if (foo) {
    return {...state, foo} as State
  } else {
    return state.foo as string
  }
}
/*
Type '(state: State, foo?: string) => string | State' is not assignable to type 'StateInteractor'.
  Type 'string | State' is not assignable to type 'string'.
    Type 'State' is not assignable to type 'string'.ts(2322)
*/

我也无法使用箭头功能/lambda。

请注意,我可以通过 function 重载来做到这一点:

function fooInteractor(state: State): string
function fooInteractor(state: State, value: string): State
function fooInteractor(state: State, value?: string) {
  if (value) {
    return {...state, foo: value} as State
  } else {
    return state.foo as string
  }
}

// This compiles and works as expected
const typedFooInteractor: StateInteractor = fooInteractor
interact(someState, typedFooInteractor)

但这非常丑陋和奇怪,并且每次我实现一个时都需要重新定义 StateInteractor 类型(通过重载)。

我们可以使用通用参数默认值条件类型作为返回值,将重载逻辑压缩到通用 function 签名中。 游乐场版

V extends string | undefined = undefined V extends string | undefined = undefined (通用默认值)表示V是字符串或未定义,默认情况下未定义。 条件返回V extends string? State: string V extends string? State: string使用三元语法根据V的类型返回。

type State = Record<string, any>

// define a function type whose return value depends on an argument
type StateInteractor = <S extends State, V extends string | undefined = undefined>(state: S, value?: V) => V extends string ? State : string 

// define an instance
const fooInteractor: StateInteractor = (state: State, foo?: string) => {
  if (foo) {
    return {...state, foo}
  } else {
    return state.foo
  }
}

// test it
const state = {foo: 'foo', other: 'data'};
const shouldBeFoo = fooInteractor(state); // returns 'foo'
const shouldBeState = fooInteractor(state, 'bar'); // return {foo: 'bar', other: 'data'}

暂无
暂无

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

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