簡體   English   中英

打字稿:傳遞函數參數的推斷類型

[英]Typescript: Infer type for parameter of passed function

我需要能夠根據已知類型的另一個參數推斷作為參數傳遞的函數的參數類型。 這有點難以解釋,所以我寫了一個小演示 ,轉載於此:

interface UnaryFunction<In, Out> {
    (arg: In): Out
}

interface WithNumber<In, Out> extends UnaryFunction<In, Out> {
    num: number
}

function testExtends<Arg, Fn extends UnaryFunction<Arg, any>>(arg: Arg, fn: Fn): Fn {
    return fn;
}

function testInferred<Arg, Out>(arg: Arg, fn: UnaryFunction<Arg, Out>): typeof fn {
    return fn
}

function mapWithCaller<From, To>(morphism: UnaryFunction<From, To>): WithNumber<From, To> {
    return Object.assign((x: From) => morphism(x), {num: 5})
}

// Error: property length does not exist
testExtends('1', mapWithCaller(x => x.length)).num
// Error: property num does not exist
testInferred('1', mapWithCaller(x => x.length)).num

如您所見,使用testExtends保留函數的返回類型,而使用testInferred推斷傳遞函數的參數類型。

我需要能夠結合兩者的優點,這讓我發瘋,這根本不可能嗎? 這是一個錯誤嗎? 按設計?

testInferred的返回類型的問題是相當明顯的 - 它是非泛型的,並且返回類型是完全固定在UnaryFunction

testExtends的問題更復雜。 這里的根本原因是你需要mapWithCaller的參數由一個能夠為參數提供上下文類型的函數類型進行上下文類型化

你實際上有一個稍微間接的上下文類型,因為mapWithCaller本身是通用的,但是因為提供了testInferred的另一個參數,並且TypeScript可以將testInferred的預期返回類型mapWithCaller回其參數,所以這不是問題。

無論如何, testInferred在這里工作,因為UnaryFunction<In, Out>是一個具有單個調用簽名的非泛型函數類型。

為什么testExtends不適用於此? 因為基於extends子句中的綁定將上下文類型應用於參數是不安全的。 考慮這個調用,這是合法的(除了lambda表達式中的錯誤):

interface OtherFunction<Out> {
    (arg: string | number): Out
}

testExtends<string, OtherFunction<number>>('1', mapWithCaller(x => x.length));

基於此處合法通用實例化允許 mapWithCallernumber傳遞給其回調。 TypeScript不能真正假設在一個位置給定一個字符串參數,函數表達式的正確推斷邊界就是這樣。

我不認為有辦法在這里編寫函數聲明,以保留你想要的兩種行為,但我可能是錯的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM