TypeScript 泛型:如何定义结构上与其他类型 S 相同的类型 T
TypeScript generics: how to define type T which is structurally the same as other type S
我有一个 Step
的概念,它需要 A
类型的值作为输入并给出 B
.
类型的值
class Step<A, B> {
constructor(private readonly f: (a: A) => B) { }
public run(a: A): B {
return this.f(a);
}
}
现在我想组合两个步骤,所以我在里面得到了这样的东西 class Step
:
public andThen<C, D>(nextStep: Step<C, D>): Step<A, D> {
return new Step<A, D>((state: A) => {
const b: B = this.f(state);
return nextStep.run(b); // <---- compile error, B and C have no relation defined
});
}
我想要实现的是以某种方式告诉类型系统我们可以将类型 B
传递给需要类型 C
的函数(结构类型应该检查 C
出现在 B
) 中,因此行 return nextStep.run(b)
工作正常。
示例:
const stepA: Step<{}, {a: number, b: string}> = new Step((input: {}) => ({ a: 5, b: "five" }));
const stepB: Step<{a: number}, {c: number}> = new Step((input: {a: number}) => ({c: input.a + 5}));
const steps = stepA.andThen(stepB)
如您所见,stepB
需要输入 {a: number}
,因此它可以从 stepA
得到输出 {a: number, b: string}
。但是我不知道如何定义 andThen
中的关系。有什么想法可以实现吗?
type SubType<T, WiderT> = T extends WiderT ? WiderT : never;
class Step<A, B> {
constructor(private readonly f: (a: A) => B) { }
public run(a: A): B {
return this.f(a);
}
public andThen<C, D>(nextStep: Step<SubType<B, C> | B, D>): Step<A, D> {
return new Step<A, D>((state: A) => {
const b = this.f(state);
return nextStep.run(b);
});
}
}
const stepAB: Step<{}, {a: number, b: string}> =
new Step((input) => ({ a: 5, b: "five" }));
const add5 = ({ a }: { a: number }) => ({ c: a + 5 });
const stepCD: Step<{ a: number }, { c: number }> = new Step(add5);
const stepAD = stepAB.andThen(stepCD);
核心点是SubType
类型:
type SubType<T, WiderT> = T extends WiderT ? WiderT : never;
它说如果类型扩展了给定的类型那么它没问题,但它不是那么永远不会。注意使用方法:
SubType<B, C> | B
所以我们说如果类型 B
扩展 C
,那么 B
是更具体的类型然后 C
那么我们允许,如果不是我们不由 never
。此外,我们允许 B
本身(没有 union 仍然存在编译错误)
我有一个 Step
的概念,它需要 A
类型的值作为输入并给出 B
.
class Step<A, B> {
constructor(private readonly f: (a: A) => B) { }
public run(a: A): B {
return this.f(a);
}
}
现在我想组合两个步骤,所以我在里面得到了这样的东西 class Step
:
public andThen<C, D>(nextStep: Step<C, D>): Step<A, D> {
return new Step<A, D>((state: A) => {
const b: B = this.f(state);
return nextStep.run(b); // <---- compile error, B and C have no relation defined
});
}
我想要实现的是以某种方式告诉类型系统我们可以将类型 B
传递给需要类型 C
的函数(结构类型应该检查 C
出现在 B
) 中,因此行 return nextStep.run(b)
工作正常。
示例:
const stepA: Step<{}, {a: number, b: string}> = new Step((input: {}) => ({ a: 5, b: "five" }));
const stepB: Step<{a: number}, {c: number}> = new Step((input: {a: number}) => ({c: input.a + 5}));
const steps = stepA.andThen(stepB)
如您所见,stepB
需要输入 {a: number}
,因此它可以从 stepA
得到输出 {a: number, b: string}
。但是我不知道如何定义 andThen
中的关系。有什么想法可以实现吗?
type SubType<T, WiderT> = T extends WiderT ? WiderT : never;
class Step<A, B> {
constructor(private readonly f: (a: A) => B) { }
public run(a: A): B {
return this.f(a);
}
public andThen<C, D>(nextStep: Step<SubType<B, C> | B, D>): Step<A, D> {
return new Step<A, D>((state: A) => {
const b = this.f(state);
return nextStep.run(b);
});
}
}
const stepAB: Step<{}, {a: number, b: string}> =
new Step((input) => ({ a: 5, b: "five" }));
const add5 = ({ a }: { a: number }) => ({ c: a + 5 });
const stepCD: Step<{ a: number }, { c: number }> = new Step(add5);
const stepAD = stepAB.andThen(stepCD);
核心点是SubType
类型:
type SubType<T, WiderT> = T extends WiderT ? WiderT : never;
它说如果类型扩展了给定的类型那么它没问题,但它不是那么永远不会。注意使用方法:
SubType<B, C> | B
所以我们说如果类型 B
扩展 C
,那么 B
是更具体的类型然后 C
那么我们允许,如果不是我们不由 never
。此外,我们允许 B
本身(没有 union 仍然存在编译错误)