- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想构建这样的东西:
type MyValues = "good" | "bad" | "ugly"
function doSomething(values:MyValues) {
return startBuilder(values)
.case("good", 1)
.case("bad", 2)
.exhaustive() // this should give an compiler error, since I forgot the `ugly` }
我尝试使用 TypeScript 的 infer
找出 tail
- 但没有成功:
type Extract<T, A> = A extends T
? T extends infer Tail
? Tail
: never
: never;
type X = Extract<Values, 'good'>;
但这行不通。有什么想法吗?
这是一个 Playground :https://stackblitz.com/edit/typescript-mguypt
最佳答案
我们首先需要一个类型来检查两个类型是否完全相等,一个简单的 extends
不会在这里做伎俩:
type Equals<A, B> = (<T>() => T extends A ? true : false) extends (<T>() => T extends B ? true : false) ? true : false;
可以在 here 中找到为什么这种看起来很有趣的类型有效的解释。由 jcalz 提供。
然后我们定义Builder类:
class Builder<T, SoFar extends ReadonlyArray<unknown> = []> {
private cases = new Map<T, unknown>();
}
它需要一个通用的 T
这是它将检查其案例的内容,并且是不打算由最终用户传递的通用名称。这个通用 SoFar
存储到目前为止使用了哪些案例。
那么让我们构建 case
现在运行:
case<V extends T>(v: V, d: unknown): Builder<T, [...SoFar, V]> {
this.cases.set(v, d);
return this as Builder<T, [...SoFar, V]>;
}
它需要扩展 T
的东西和任何值,然后将生成器返回为 Builder<T, [...SoFar, V]>
,这意味着我们将案例添加到目前用完的案例中。
终于到了:
exhaustive(...args: Equals<T, SoFar[number]> extends true ? [] : [{ error: "Builder is not exhaustive." }]) {
}
我们检查是否T
和 SoFar[number]
是完全一样的。如果是,那么我们已经用尽了所有情况。否则,我们说我们期待一个参数。
因为您可能会调用 exhaustive
没有参数,调用它而不用完所有情况将为用户显示一条很好的错误消息。
您甚至可以更进一步,在错误消息中包含所有缺失的案例!第二个 Playground 链接演示了这一点。
关于typescript - 检查构建器模式中的详尽性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72117512/
我有一个实用函数来在引用中存储不断变化的值: export function useRefOf(value: T) { const ref = useRef(value); useEffect
我是一名优秀的程序员,十分优秀!