打字稿:函数参数的类型辅助
Posted
技术标签:
【中文标题】打字稿:函数参数的类型辅助【英文标题】:Typescript: type assist for function argument 【发布时间】:2022-01-12 19:52:17 【问题描述】:我已经编写了一个小库,现在我正在尝试通过创建自定义 d.ts 文件来为其添加类型支持。
举个例子(我的库叫做layerCompose
):
const C = layerCompose(
_($) /* function body */ ,
execute($) /* function body */
)
const c = C()
c._()
您会注意到_
和execute
函数都带有一个参数$
。
此参数(在我们的示例中)是具有_
和execute
属性的对象(类似于类中的this
)
所以,我想为这个$
参数添加类型支持。通过实验,我发现在我的 d.ts 文件中包含此定义可以在 _
函数中提供类型支持。
export function layerCompose<
T extends [
A extends
?
_($: test: () => void)
: never
]
, A
>(...layers: T): lcConstructor<Spread<T>>
也就是说Webstorm可以看到_
函数中的$
参数的类型是test: () => void
显然,这不是我想要的。但是,将签名更改为(我认为合适的)
export function layerCompose<
T extends [
A extends
?
[K in keyof A]: ($: test: () => void) => any
: never
]
, A
>(...layers: T): lcConstructor<Spread<T>>
Webstorm 失去了判断$
是具有_
和execute
属性的对象的能力。
编辑:Included an example on typescript playground。它缺少返回类型(快速设置它并非易事),但可以深入了解layerCompose
的大致作用。
编辑 2:
进一步玩,已简化为 1 个参数场景,这是可行的:
export function layerCompose<L1>(l1: _: ($: test: () => void) => void & L1): void
但事实并非如此:
export function layerCompose<L1>(l1: [K in keyof L1]: ($: test: () => void) => void & L1): void
【问题讨论】:
A
是如何被解析的,为什么在函数签名中没有用到它?您应该为您的问题编写一个完全可重现的示例。 typescriptlang.org/play 将受到欢迎
您提供的用于键入layerCompose
的示例始终会生成T = never
。你确定他们被使用了吗? Webstorm 可能无法正确识别您的声明文件。
@GuerricP 示例已添加。
@Olian04 我一直在努力确保传播对我的 d.ts 文件的更新。我可以看到 Webstorm 何时获取签名以及何时失败。
【参考方案1】:
这就是你要找的吗?
export function layerCompose(...layers: Layer[]): lcConstructor<Spread<T>>;
由于您既没有定义lcConstructor
或Spread
,所以我无法真正猜测layerCompose
的返回类型应该是什么。因此,出于此答案的目的,这些类型已替换为身份类型。
// See playground below
type ComposedLayer =
_(): void;
execute(): void;
type Layer =
_(v: Layer): void;
execute(v: Layer): void;
/* dummy type */ type lcConstructor<T> = ComposedLayer;
/* dummy type */ type Spread<T> = T;
declare function layerCompose(...layers: Layer[]): lcConstructor<Spread<Layer>>;
const C = layerCompose(
_($) ,
execute($)
$._(
_($) ,
execute($)
)
);
C._();
playground
【讨论】:
看看我提供的游乐场示例。麻烦的是我提前不知道Layer
的形状。【参考方案2】:
根据个人经验,先找个泛型类型,避免循环依赖。请检查以下定义。
type Layer<K extends string> = Partial<Record<K, ($: Record<K, Function>) => void>>
function layerCompose<K extends string>(...layers: Layer<K>[]): Record<K, Function>
// ignore how do you implement to match types
return as Record<K, Function>
【讨论】:
以上是关于打字稿:函数参数的类型辅助的主要内容,如果未能解决你的问题,请参考以下文章