如何通过TypeScript中的映射类型删除属性和promisify方法 [英] how to remove properties and promisify method via mapped type in TypeScript
问题描述
这是代码
class A {
x = 0;
y = 0;
visible = false;
render() {
return 1;
}
}
type RemoveProperties<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : never//;
};
type JustMethodKeys<T> = ({ [P in keyof T]: T[P] extends Function ? P : never })[keyof T];
type JustMethods<T> = Pick<T, JustMethodKeys<T>>;
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type Promisified<T extends Function> =
T extends (...args: any[]) => Promise<any> ? T : (
T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => infer R ? (
IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<R> :
IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<R> :
IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<R> :
IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<R> :
IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<R> :
IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => Promise<R> :
IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => Promise<R> :
IsValidArg<C> extends true ? (a: A, b: B, c: C) => Promise<R> :
IsValidArg<B> extends true ? (a: A, b: B) => Promise<R> :
IsValidArg<A> extends true ? (a: A) => Promise<R> :
() => Promise<R>
) : never
);
var a = new A() as JustMethods<A> // I want to JustMethod && Promisified
a.visible // error
var b = a.render() // b should be Promise<number>
如何实现?我想去掉visible和promisify的render method,如何合成Promisified和JustMethods?
How to implement it ? I want to remove visible and promisify render method , how to composite Promisified and JustMethods ?
如何实现?我想去掉visible和promisify的render method,如何合成Promisified和JustMethods?
How to implement it ? I want to remove visible and promisify render method , how to composite Promisified and JustMethods ?
推荐答案
您需要使用一个映射类型,该类型仅采用使用 JustMethodKeys
的类型的方法并使用 Promisified
在每个属性上
You need to use a mapped type that takes just the methods of the type using JustMethodKeys
and uses Promisified
on each property
class A {
x = 0;
y = 0;
visible = false;
render() {
return 1;
}
}
type JustMethodKeys<T> = ({ [P in keyof T]: T[P] extends Function ? P : never })[keyof T];
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type Promisified<T extends Function> =
T extends (...args: any[]) => Promise<any> ? T : (
T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => infer R ? (
IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<R> :
IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<R> :
IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<R> :
IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<R> :
IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<R> :
IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => Promise<R> :
IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => Promise<R> :
IsValidArg<C> extends true ? (a: A, b: B, c: C) => Promise<R> :
IsValidArg<B> extends true ? (a: A, b: B) => Promise<R> :
IsValidArg<A> extends true ? (a: A) => Promise<R> :
() => Promise<R>
) : never
);
type PromisifyMethods<T> = {
// We take just the method key and Promisify them,
// We have to use T[P] & Function because the compiler will not realize T[P] will always be a function
[P in JustMethodKeys<T>] : Promisified<T[P] & Function>
}
//Usage
declare var a : PromisifyMethods<A>
a.visible // error
var b = a.render() // b is Promise<number>
编辑
自从原始问题得到回答以来,打字稿改进了这个问题的可能解决方案.通过添加 其余参数和传播表达式中的元组,我们现在不需要Promisified
的所有重载:
Since the original question was answered typescript has improved the possible solution to this problem. With the addition of Tuples in rest parameters and spread expressions we now don't need to have all the overloads for Promisified
:
type JustMethodKeys<T> = ({ [P in keyof T]: T[P] extends Function ? P : never })[keyof T];
type ArgumentTypes<T> = T extends (... args: infer U ) => any ? U: never;
type Promisified<T> = T extends (...args: any[])=> infer R ? (...a: ArgumentTypes<T>) => Promise<R> : never;
type PromisifyMethods<T> = {
// We take just the method key and Promisify them,
// We have to use T[P] & Function because the compiler will not realize T[P] will always be a function
[P in JustMethodKeys<T>] : Promisified<T[P]>
}
//Usage
declare var a : PromisifyMethods<A>
a.visible // error
var b = a.render("") // b is Promise<number> , render is render: (k: string) => Promise<number>
这不仅更短,而且解决了许多问题
Not only is this shorter but it solves a number of problems
- 可选参数保持可选
- 保留参数名称
- 适用于任意数量的参数
这篇关于如何通过TypeScript中的映射类型删除属性和promisify方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!