【发布时间】:2020-12-31 12:14:11
【问题描述】:
我已经为这个问题精简了这段代码。这是playground。
我有这个函数,它返回一个带有类型参数的函数:
export function createInteractor<E extends Element>(name: string) {
return <S extends InteractorSpecification<E, S>>(specification: InteractorSpecification<E, S>) => {
const result: unknown = {}
return result as unknown as InteractorType<E, typeof specification>;
}
}
InteractorSpecification 类型会查找一个名为 locators 的属性,该属性具有动态且由用户添加的字段
export type InteractorSpecification<E extends Element, S extends InteractorSpecification<E, S>> =
{
selector?: string;
locators: Record<keyof S['locators'], LocatorFn<E>>;
};
高阶函数返回此类型
return result as unknown as InteractorType<E, typeof specification>;
InteractorType 看起来像这样:
export type LocatorImplementation<E extends Element, S extends InteractorSpecification<E, S>> =
{[K in keyof S['locators']]: (value: string) => InteractorInstance<E, S>}
export type InteractorType<E extends Element, S extends InteractorSpecification<E, S>> = LocatorImplementation<E, S>;
基本上它从原始specification 的location 中获取属性并将它们映射到返回类型。
没有推断出高阶函数的类型参数,但如果我传入显式类型参数,它就可以工作:
const Link = createInteractor<HTMLLinkElement>('link')({
selector: 'a',
locators: {
byThis: (element) => element.href,
byThat: (element) => element.title
},
});
// type is not inferred
// const Link: LocatorImplementation<HTMLLinkElement, InteractorSpecification<HTMLLinkElement, InteractorSpecification<HTMLLinkElement, unknown>>>
Link.byThat('foo');
Link.byThis('bar')
const spec = {
selector: 'a',
locators: {
byThis: (element: HTMLLinkElement) => element.href,
byThat: (element: HTMLLinkElement) => element.title
},
asfsdfsd: 'I also need to catch unknown props'
}
// works with explicit type
const F = createInteractor<HTMLLinkElement>('link')<typeof spec>(spec)
F.byThat('foo');
F.byThis('bar');
【问题讨论】:
标签: typescript