考慮以下 JS 函式和示例用法:
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 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 型別(通過多載)。
uj5u.com熱心網友回復:
我們可以使用通用引數默認值和條件型別作為回傳值將多載邏輯壓縮到通用函式簽名中。 游樂場版
V extends string | undefined = undefined(通用默認值)表示V是字串或未定義,默認情況下未定義。條件回傳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'}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/370080.html
標籤:打字稿
上一篇:帶十進制數的打字稿減法
