在学习TypeScript的过程中,我试图创建一个函数,该函数将从输入参数中推导出返回值,作为一个字典,其中的值定义为具有适当类型的函数对象。
最初这是从弗里达类型库。
我试图扩展一个功能来定义函数的API。
我所面临的问题,我可以在一个小片段中说明,当将类型直接传递给另一个泛型类型时,inferred关键字似乎可以工作,**但是当类型从函数参数推导出来时,一切都失败了。
我有下面的代码片段用最少的代码来说明这个问题
declare class Pointer {}
type NativeTypesMap = {
int: number;
long: number;
void: void;
pointer: Pointer;
};
type ValuesOf<T> = T[keyof T];
type KeysOf<T> = keyof T;
type NativeTypesValue = ValuesOf<NativeTypesMap>;
type NativeTypesType = KeysOf<NativeTypesMap>;
type GetValue<Map, Type, T extends Type> = T extends keyof Map ? Map[T] : never;
type GetArgValue<T extends NativeTypesType> = GetValue<
NativeTypesMap,
NativeTypesType,
T
>;
type Def<T extends NativeTypesType> = { r: T };
type DefAny = Def<any>;
declare type BaseApi = {
[k: string]: DefAny;
};
type ApiCalls<T extends BaseApi> = {
[p in keyof T]: T[p] extends Def<infer R>
? (...args: any) => GetArgValue<R>
: never;
};
function createapi<T extends BaseApi>(params: T): ApiCalls<T> {
// implementation omitted
return {} as ApiCalls<T>;
}
type z = ApiCalls<{
open: { r: "int" };
malloc: { r: "pointer" };
free: { r: "void" };
}>;
/*
* z is calculated to be
* type z = {
* open: (...args: any) => number;
* malloc: (...args: any) => Pointer;
* free: (...args: any) => void;
* }
*/
var a = createapi({
open: { r: "int" },
malloc: { r: "pointer" },
free: { r: "void" },
});
type c = typeof a;
/*
* calculated type of a is:
* tyoepf a = {
* open: never;
* malloc: never;
* free: never;
* }
*/
字符串
TS Playground
我的目标是改变createapi,使a的dedcued类型与z相同。
有人知道我错过了什么吗?
1条答案
按热度按时间wqsoz72f1#
这个问题是因为你传递给函数的对象的类型:
字符串
编译器将类型扩展为基本类型,以便在处理变量时使我们的工作更轻松。由于
obj
的属性中不再有文字值,因此infer
条件不再起作用。有两种方法可以解决此问题:
const assertion -防止typescript扩大类型:
型
测试:
型
看起来不错,但是,在每个函数调用中添加
as const
会变得非常烦人和不方便。在Typescript 5.0
中,添加了const类型参数,它们的作用与 const assertion 对函数参数的作用相同:型