是否可以在TypeScript中执行类似this的操作?
如果没有,是否有正式解释为什么编译器无法推断嵌套类型参数?
以下是我尝试实现的一个例子:
interface TestFilter {
name?: string;
}
interface FilterComponent<F> {
setFilter(filter: F)
}
class TestFilterComponent implements FilterComponent<TestFilter> {
private filter: TestFilter;
setFilter(filter: TestFilter) {
this.filter = filter;
}
}
// Can I use F without declaring it as another type parameter?
// Something like: class FilterWrapperComponent<FC extends FilterComponent<F>>
abstract class FilterWrapperComponent<F, FC extends FilterComponent<F>> {
private sidebarFilter: FC;
private modalFilter: FC;
public passFilter(filter: F) {
this.sidebarFilter.setFilter(filter);
this.modalFilter.setFilter(filter);
}
}
// I want to just write "extends FilterWrapperComponent<TestFilterComponent>"
// and get TestFilter as F automatically
class TestFilterWrapperComponent extends FilterWrapperComponent<TestFilter, TestFilterComponent> {
}
也可在playground上找到。
答案 0 :(得分:1)
您可以在当前处于候选发布候选状态的TypeScript 2.8中安装typescript@rc
。
TypeScript 2.8附带条件类型和条件类型的类型推断。你真正想要的是通用约束中的类型推断,但这不是直接可能的,解决方法是使用在else分支中解析为never
的条件类型。
interface FilterComponent<F = any> {
setFilter(filter: F)
}
type ExtractFilter<C extends FilterComponent> = C['setFilter'] extends (filter: infer F) => void ? F : never;
现在你可以像这样编写你的类:
abstract class FilterWrapperComponent<FC extends FilterComponent> {
private sidebarFilter: FC;
private modalFilter: FC;
public passFilter(filter: ExtractFilter<FC>) {
this.sidebarFilter.setFilter(filter);
this.modalFilter.setFilter(filter);
}
}
class TestFilterWrapperComponent extends FilterWrapperComponent<TestFilterComponent> {
}
答案 1 :(得分:1)
默认情况下,通用参数值为{}
。它在省略参数时适用。可以使用generic parameter defaults更改默认值。
我想写“extends FilterWrapperComponent” 并自动将TestFilter作为F
这可以通过仅指定FilterComponent<TestFilter>
来获得TestFilter
和TestFilter
的相反方式:
abstract class FilterWrapperComponent<F, FC = FilterComponent<F>> {}
class TestFilterWrapperComponent extends FilterWrapperComponent<TestFilter> {}
答案 2 :(得分:1)
使用 infer
语句,您可以推断类型 inside conditional types。
这意味着您可以提取另一种类型中“隐藏”的类型。
接下来,我编写了 UnwrapFilter
,它从 Filter
类型中提取 FilterComponent
泛型参数。
type UnwrapFilter<T extends FilterComponent<any>> = T extends FilterComponent<infer TC> ? TC : never;
abstract class FilterWrapperComponent2<FC extends FilterComponent<any>> {
constructor(
private sidebarFilter: FC,
private modalFilter: FC,
) {}
public passFilter(filter: UnwrapFilter<FC>) {
this.sidebarFilter.setFilter(filter);
this.modalFilter.setFilter(filter);
}
}
我不确定是否可以编写更通用的版本 - 不依赖于特定的 FilterComponent
类型 - UnwrapFilter
。
这是因为 infer
语句似乎要求 T
是 extends
之后的任何内容的直接实例化,即在以下示例中,T1
被正确推断,但 {{ 1}} 不是。
T2
在其他情况下,可以使用 类型查询 - 现在在文档中称为 Indexed Access Types - 可以使用。
在此示例中,interface OneParamGeneric<T> {}
type UnwrapOneParam<T extends OneParamGeneric<{}>> = T extends OneParamGeneric<infer TypeArg> ? TypeArg : never;
type T1 = UnwrapOneParam<OneParamGeneric<TestFilter>>;
type T2 = UnwrapOneParam<FilterComponent<TestFilter>>;
将 PublicFilterComponent
公开为字段,从而允许通过方括号语法 activeFilter
进行访问。
PublicFilterComponent['activeFilter']