[英]any class as function argument in typescript
Suggestion needed: As a newbie, I have class like below in typescript :需要的建议:作为一个新手,我在 typescript 中有如下class :
export declare class SampleOne extends Setting {
getValue(): Promise<boolean>;
setValue(value: boolean): Promise<void>;
}
And和
export declare class SampleTwo extends Setting {
getValue(): Promise<boolean>;
setValue(value: boolean): Promise<void>;
}
Now i want a helper function where i can pass either SampleOne or SampleTwo like below:现在我想要一个助手 function 我可以通过SampleOne或SampleTwo如下所示:
async function getObj(title: string, categories: string, cname: Setting) {
let obj = await et.findSetting(title,categories) as cname;// i want to pass either **SammpleOne** or **SampleTwo** class.
return obj;
}
Function call would be like Function 调用就像
getObj(title, categories, SampleOne) getObj(标题,类别,SampleOne)
getObj(title, categories, SampleTwo) getObj(标题,类别,SampleTwo)
I am strangling to created this helper function.How it should be looks like in typescript??我正在扼杀创建这个助手 function。它在 typescript 中应该是什么样子?
Thanks in advance.提前致谢。
You can make getObj
generic by the type of Setting
and parametrize the last argument as a constructor of T:您可以通过Setting
的类型使getObj
通用,并将最后一个参数参数化为 T 的构造函数:
type Class<T> = new (...args: any) => T;
async function getObj<T extends Setting>(
title: string, categories: string, klass: Class<T>): Promise<T>
{
return .... as T
}
I would go with Convenience generic pattern我会使用方便通用模式的 go
async function getObj<T extends Setting>(title: string, categories: string): Promise<T> {
let obj = await et.findSetting(title,categories) as T;
return obj;
}
or, dropping the unncecessary async:或者,删除不必要的异步:
function getObj<T extends Setting>(title: string, categories: string): Promise<T> {
return et.findSetting(title,categories) as Promise<T>;
}
Usage:用法:
const s1 = getObj<SampleOne>('a', 'b');
Pros:优点:
Cons:缺点:
If you need runtime check and have settings modeled as classes, you can use Type (as coded by Angular folks):如果您需要运行时检查并将设置建模为类,则可以使用Type (由 Angular 人员编码):
interface Type<T> extends Function { new (...args: any[]): T; }
async function getObj<T extends Setting>(
title: string, categories: string, klass: Type<T>): Promise<T>
{
let obj = await et.findSetting(title,categories);
if (klass.prototype.isPrototypeOf(obj)) {
return obj as T;
} else {
throw new Error(`Expected ${klass.name} but got ${obj.constructor.name}`)
}
}
const s1 = getObj('a', 'b', SampleOne);
s1.then(x => console.log(x))
.catch(e => console.log(e));
I believe you can just apply this constraint T extends typeof Setting
to generic:我相信你可以只应用这个约束T extends typeof Setting
到泛型:
class Setting {
getValue(): Promise<boolean> { return Promise.resolve(true) };
setValue(value: boolean): Promise<void> { return Promise.resolve() };
}
class SampleOne extends Setting {
getValue(): Promise<boolean> { return Promise.resolve(true) };
setValue(value: boolean): Promise<void> { return Promise.resolve() };
}
class SampleTwo extends Setting {
getValue(): Promise<boolean> { return Promise.resolve(true) };
setValue(value: boolean): Promise<void> { return Promise.resolve() };
}
class DontAllowed { }
type AllowedClasses = typeof SampleOne | typeof SampleTwo
class SampleThree { // does not extends Setting
getValue(): Promise<boolean> { return Promise.resolve(true) };
setValue(value: boolean): Promise<void> { return Promise.resolve() };
}
function getObj<T extends typeof Setting>(cname: T) {
return cname
}
const result = getObj(SampleOne) // ok
const result2 = getObj(SampleTwo) // ok
const result3 = getObj(DontAllowed) // expected error
In above example, I assumed that every class which extends Setting is allowed.在上面的例子中,我假设每个扩展设置的 class 都是允许的。 If you want to allow anly two classes, you can do this thing:如果你想只允许两个类,你可以这样做:
type AllowedClasses = typeof SampleOne | typeof SampleTwo
function getObj<T extends AllowedClasses>(cname: T) {
return cname
}
I don't think that it is necessary to use type assertion ( as
operator) in such cases.我认为在这种情况下没有必要使用类型断言( as
运算符)。
async function getObj<T>(title: string, categories: string) {
let obj = await et.findSetting(title,categories) as T;
return obj;
}
Then you can call the function with the desired type:然后您可以使用所需的类型调用 function:
getObj<SampleOne>('foo', 'bar');
getObj<SampleTwo>('foo', 'bar');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.