typescript - 用于函数参数的 TypeScript 接口和泛型
问题描述
我需要创建多个测试,并且我想确保设置是强类型的。我正在阅读泛型文档,我可以理解简单的案例,但我迷失了高级示例。
我尝试做一些类似于上一个例子中描述的事情。
有两个测试函数签名,根据测试值和条件值而变化:
interface ITestFuncWithCond<ValueType, ConditionType> {
(value: ValueType, condition: ConditionType): boolean;
};
interface ITestFuncNoCond<ValueType> {
(value: ValueType): boolean;
};
这个想法是对测试做这样的事情(注意类型):
// Example A
// No condition param
const testA: Tester = createTest(StringTestIsEmpty);
// Value param type must be string.
testA.test("myString");
// Example B
// condition param is number
const testB: Tester = createTest(StringLengthEquals, 2);
// Value param type must be string.
testB.test("myString");
// Example C
// condition param is string
const testC: Tester = createTest(StringEquals, "myString");
// Value param type must be string.
testC.test("myString");
// Example D
// condition param is number
const testD: Tester = createTest(NumberEquals, 10);
// Value param type must be number.
testD.test(5);
这是我的伪代码,但正如你可能看到的,我需要一些指导词来解开这个问题。
我更新了下面的代码,试图更好地解释我在找什么。 这是一个沙箱
// Test implementations
const _StringTestIsEmpty = (x: string): boolean => {
console.log(x);
return x === "";
}
const _StringLengthEquals = (x: string, l: number): boolean => {
console.log(x, l);
return x.length === l;
}
const _StringEquals = (x: string, y: string): boolean => {
console.log(x, y);
return x === y;
}
const _NumberEquals = (x: number, y: number): boolean => {
console.log(x, y);
return x === y;
}
// Different tests available
enum TestName {
StringTestIsEmpty,
StringLengthEquals,
StringEquals,
NumberEquals
}
// Test signatures.
interface ITestFuncWithCond<ValueType, ConditionType> {
(value: ValueType, condition: ConditionType): boolean;
};
interface ITestFuncNoCond<ValueType> {
(value: ValueType): boolean;
};
class Tester<ConditionType, ValueType> {
name: TestName;
condition?: ConditionType;
// ValueType??? ConditionType ???
private testFunction: ITestFuncWithCond<ValueType, ConditionType> | ITestFuncNoCond<ValueType>
// Test constructor with different signatures.
constructor(testName: TestName);
constructor(testName: TestName, condition: ConditionType);
constructor(testName: TestName, condition?: ConditionType) {
this.name = testName;
this.condition = condition;
// Here, the testName is used to fetch the actual test function (testImpl)
this.testFunction = this.getFunction(testName)
}
// ValueType should be string for test A, B and C, and should be number for test D.
// "this.condition" should be undefined in test A.
// "this.condition" should be "number for test B and D, and "string" for testC.
test(value: ValueType): boolean {
if (this.condition) {
return this.testFunction(value, this.condition);
} else {
return this.testFunction(value);
}
}
private fetchTestFunction<V, C extends [] | [condition: any]>(iTestFunc: (value: V, ...conditionMaybe: C) => boolean, ...conditionMaybe: C) {
return {
test: (v: V) => iTestFunc(v, ...conditionMaybe)
}
}
private getFunction(testName: TestName) {
switch (testName) {
case TestName.StringTestIsEmpty: {
return this.fetchTestFunction(_StringTestIsEmpty);
}
case TestName.StringLengthEquals: {
return this.fetchTestFunction(_StringLengthEquals, this.condition);
}
case TestName.StringEquals: {
return this.fetchTestFunction(_StringEquals, this.condition);
}
case TestName.NumberEquals: {
return this.fetchTestFunction(_NumberEquals, this.condition);
}
}
}
}
function createTest(testName: TestName, condition?: any): Tester {
// set up to properly fetch the right test
return new Tester(testName, condition);
}
// Example A
// No condition param
// don't annotate Tester because it must be generic
const testA = createTest(TestName.StringTestIsEmpty);
// Value param type must be string.
testA.test("myString");
// Example B
// condition param is number
const testB = createTest(TestName.StringLengthEquals, 2);
// Value param type must be string.
testB.test("myString");
// Example C
// condition param is string
const testC = createTest(TestName.StringEquals, "myString");
// Value param type must be string.
testC.test("myString");
// Example D
// condition param is number
const testD = createTest(TestName.NumberEquals, 10);
// Value param type must be number.
testD.test(5);
解决方案
推荐阅读
- azure-devops-server - 如何替换 Artifacts 中的包
- ruby - How to run "git blame" on a given set of files using Octokit
- php - Wordpress woocommerce update product stock and status via php mysql
- pandas - pandas - 使用字典映射数据框元素 - 如何访问值列表的第 n 个元素
- go - 无法在多重赋值中将字符串赋值给 __type__(类型 __type__ )
- regex - 捕获每组的所有文本
- python - 如何准备数据并进行自编码器的训练?
- php - 数组中的表单在 if 语句后不显示按钮
- google-chrome-extension - 切换到 v3 后从 Chrome 扩展程序进行 Google 身份验证
- linux - Apache将所有路径映射到根目录而不重定向