TypeScript 中柯里化函数的类型推断
Type inference in TypeScript for curried function
我在 TypeScript 中对柯里化函数有以下定义:
interface Curried2<A, B, Z> {
(_0: A): (_0: B) => Z;
(_0: A, _1: B): Z;
}
我有以下函数应该接受一个函数(柯里化与否):
function apply<T, U>(f: (_0: T) => U, x: T): U {
return f(x);
}
现在给定
let curried: Curried2<number, boolean, string> = ...
以下作品(如预期):
apply<number, (_0: boolean) => string>(curried, 4);
但是 TypeScript 无法自行推断类型:
apply(curried, 4);
(即使 ()
只有一个重载采用 单个值 。)它抱怨:
Argument of type 'Curried2<number, boolean, string>' is not assignable to parameter of type '(_0: number) => string' ...
它已正确推断 T
,但推断 U
为 string
。为什么是这样?在这种情况下,我该怎么做才能使类型推断对我有用(因为明确指定 T
和 U
对我来说太冗长了)?
提前致谢!
我可以试试这个方法:
type Curried<T1, T2, T3> = (x: T1) => (y: T2) => T3;
function apply<T, U>(f: (value: T) => U, x: T): U {
return f(x);
}
//simple demo
var someFunc: Curried<string, number, [string, number]> = x => y => [x, y];
var curriedSomeFunc = apply(someFunc, "string here");
var result1 = curriedSomeFunc(0); //will be ["string here", 0]
var result2 = curriedSomeFunc(1); //will be ["string here", 1]
再试一次。语法是正确的,但如果你传递的柯里化函数不正确,就不安全了:
interface Curried<T1, T2, T3> {
(x: T1, y: T2): T3;
(x: T1): (y: T2) => T3
}
let f1 = <Curried<string, number, [string, number]>>
((x: string, y: number) => [x, 1]);
let f2 = <Curried<string, number, [string, number]>>
((x: string) => (y: number) => [x, y]);
function apply<T, V>(f: (x: T) => V, x: T): V {
return f(x);
}
let curriedF1 = apply(f1, "42"); //Won't work (no function to curry) but type inference is OK
let curriedF2 = apply(f2, "11"); //Will work and type inference is also OK
以下现在有效:
interface F1<A, Z> {
(_0: A): Z;
}
interface F2<A, B, Z> extends F1<A, F1<B, Z>> {
(_0: A, _1: B): Z;
}
function apply<T, U>(f: F1<T, U>, x: T): U {
return f(x);
}
function apply2<T, U, V>(f: F2<T, U, V>, x: T, y: U): V {
return f(x, y);
}
let curried: F2<number, boolean, string> = null;
const x: F1<boolean, string> = apply(curried, 4);
const y: string = apply2(curried, 4, false);
我在 TypeScript 中对柯里化函数有以下定义:
interface Curried2<A, B, Z> {
(_0: A): (_0: B) => Z;
(_0: A, _1: B): Z;
}
我有以下函数应该接受一个函数(柯里化与否):
function apply<T, U>(f: (_0: T) => U, x: T): U {
return f(x);
}
现在给定
let curried: Curried2<number, boolean, string> = ...
以下作品(如预期):
apply<number, (_0: boolean) => string>(curried, 4);
但是 TypeScript 无法自行推断类型:
apply(curried, 4);
(即使 ()
只有一个重载采用 单个值 。)它抱怨:
Argument of type 'Curried2<number, boolean, string>' is not assignable to parameter of type '(_0: number) => string' ...它已正确推断
T
,但推断 U
为 string
。为什么是这样?在这种情况下,我该怎么做才能使类型推断对我有用(因为明确指定 T
和 U
对我来说太冗长了)?
提前致谢!
我可以试试这个方法:
type Curried<T1, T2, T3> = (x: T1) => (y: T2) => T3;
function apply<T, U>(f: (value: T) => U, x: T): U {
return f(x);
}
//simple demo
var someFunc: Curried<string, number, [string, number]> = x => y => [x, y];
var curriedSomeFunc = apply(someFunc, "string here");
var result1 = curriedSomeFunc(0); //will be ["string here", 0]
var result2 = curriedSomeFunc(1); //will be ["string here", 1]
再试一次。语法是正确的,但如果你传递的柯里化函数不正确,就不安全了:
interface Curried<T1, T2, T3> {
(x: T1, y: T2): T3;
(x: T1): (y: T2) => T3
}
let f1 = <Curried<string, number, [string, number]>>
((x: string, y: number) => [x, 1]);
let f2 = <Curried<string, number, [string, number]>>
((x: string) => (y: number) => [x, y]);
function apply<T, V>(f: (x: T) => V, x: T): V {
return f(x);
}
let curriedF1 = apply(f1, "42"); //Won't work (no function to curry) but type inference is OK
let curriedF2 = apply(f2, "11"); //Will work and type inference is also OK
以下现在有效:
interface F1<A, Z> {
(_0: A): Z;
}
interface F2<A, B, Z> extends F1<A, F1<B, Z>> {
(_0: A, _1: B): Z;
}
function apply<T, U>(f: F1<T, U>, x: T): U {
return f(x);
}
function apply2<T, U, V>(f: F2<T, U, V>, x: T, y: U): V {
return f(x, y);
}
let curried: F2<number, boolean, string> = null;
const x: F1<boolean, string> = apply(curried, 4);
const y: string = apply2(curried, 4, false);