带有映射类型和 const 断言的 TypeScript 构建器模式
TypeScript builder pattern with mapped types and const assertion
在 TypeScript 中,我可以创建一个函数 buildOptions(options, default)
,其中 options
是一个数组,default
是一个必须来自选项数组的值。我相信这是可以做到的,因为 mapped types and const assertions.
const buildOptions = <T, K extends T[][number]>(
options: Readonly<T[]>,
defaultOption: K
) => ({
options,
default: options.findIndex(x => x === defaultOption),
});
// works
buildOptions(['a', 'b'] as const, 'a');
// compile error: Argument of type '4' is not assignable to parameter of type '2 | 1 | 3'.
buildOptions([1, 2, 3] as const, 4);
是否可以使用构建器模式添加此级别的键入?我想要一个类似于以下内容的界面:
optionBuilder()
.addOption(1)
.addOption(2)
.addOption(3)
.setDefault(4) // compile error
.build();
或者可能:
optionBuilder()
.addOptions([1, 2, 3] as const)
.setDefault(4) // compile error
.build();
如果这不能在 TypeScript 中完成,有人知道可以用什么语言完成吗?
谢谢!
是的,我们可以:)
class Builder<T> {
addOption<V>(v: V): Builder<T | V> {
// do your stuff
return this as Builder<T | V>;
}
setDefault(v: T): this {
// do your stuff
return this;
}
build(): T[] {
// return list of all options ??
}
}
function optionBuilder(): Builder<never> {
return new Builder();
}
optionBuilder()
.addOption(1 as const)
.addOption('str' as const)
.setDefault(1) // OK
.setDefault(12) // compile error
.setDefault('str') // OK
.setDefault('strstr') // compile error
.build();
注意
- 所有
as const
都是必须的,否则1
被认为是number
(例如);
optionBuilder
的 return 类型的 never
类型是必要的,以确保我们的构建器完全没有类型,否则它将使用 unknown
相反,接受一切;
希望有更好的解决办法!
在 TypeScript 中,我可以创建一个函数 buildOptions(options, default)
,其中 options
是一个数组,default
是一个必须来自选项数组的值。我相信这是可以做到的,因为 mapped types and const assertions.
const buildOptions = <T, K extends T[][number]>(
options: Readonly<T[]>,
defaultOption: K
) => ({
options,
default: options.findIndex(x => x === defaultOption),
});
// works
buildOptions(['a', 'b'] as const, 'a');
// compile error: Argument of type '4' is not assignable to parameter of type '2 | 1 | 3'.
buildOptions([1, 2, 3] as const, 4);
是否可以使用构建器模式添加此级别的键入?我想要一个类似于以下内容的界面:
optionBuilder()
.addOption(1)
.addOption(2)
.addOption(3)
.setDefault(4) // compile error
.build();
或者可能:
optionBuilder()
.addOptions([1, 2, 3] as const)
.setDefault(4) // compile error
.build();
如果这不能在 TypeScript 中完成,有人知道可以用什么语言完成吗?
谢谢!
是的,我们可以:)
class Builder<T> {
addOption<V>(v: V): Builder<T | V> {
// do your stuff
return this as Builder<T | V>;
}
setDefault(v: T): this {
// do your stuff
return this;
}
build(): T[] {
// return list of all options ??
}
}
function optionBuilder(): Builder<never> {
return new Builder();
}
optionBuilder()
.addOption(1 as const)
.addOption('str' as const)
.setDefault(1) // OK
.setDefault(12) // compile error
.setDefault('str') // OK
.setDefault('strstr') // compile error
.build();
注意
- 所有
as const
都是必须的,否则1
被认为是number
(例如); optionBuilder
的 return 类型的never
类型是必要的,以确保我们的构建器完全没有类型,否则它将使用unknown
相反,接受一切;
希望有更好的解决办法!