class 中的混合文字和数组参数类型与泛型
Mixed literal and array parameter type in class with generics
我有一个class这样的
class Schema<T extends "foo" | string[]> {
constructor(public value: T) {}
}
为此,构造函数应接受字符串文字“foo”或任意字符串数组。实例化应该 return 一个仅使用文字类型的对象(对于数组也是联合文字):
// What I would like to have
new Schema(["x", "y"]) // => Schema<"x" | "y">
new Schema("foo") // => Schema<"foo">
上面的 class 实现不是这种情况(它 return 在提供数组时是 Schema<string[]>
类型的对象)。
但是如果我这样定义我的class
class Schema<T extends "foo" | string> {
constructor(public value: T[]) {}
}
我失去了呼叫 new Schema("foo")
的选项。
有什么打字功夫可以解决这个问题吗?
这里有最简单的方法:
class Schema<Value extends string, Values extends string[]> {
constructor(value: Value | [...Values]) { }
}
// What I would like to have
new Schema(["x", "y"]) // Schema<string, ["x", "y"]>
new Schema("foo") // Schema<"foo", string[]>
正如您已经注意到的,额外的 string
或 string[]
泛型存在问题。
我认为我们可以做得更好。
因为 constructor
不允许我们使用泛型,我们可以创建额外的 method
用于推理目的。
class Schema {
register<Value extends string>(value: Value): asserts this is { value: Value }
register<Value extends string[]>(value: [...Value]): asserts this is { value: Value[number] }
register<Value extends string | string[]>(value: Value): asserts this is { value: Value } {
}
}
const result: Schema = new Schema();
result.value // expected error
result.register(['x', 'y']);
result.value // x | y
Here you can find docs about asserts
and here 关于函数重载。
请告诉我它是否适合您以及是否需要改进。谢谢
我有一个class这样的
class Schema<T extends "foo" | string[]> {
constructor(public value: T) {}
}
为此,构造函数应接受字符串文字“foo”或任意字符串数组。实例化应该 return 一个仅使用文字类型的对象(对于数组也是联合文字):
// What I would like to have
new Schema(["x", "y"]) // => Schema<"x" | "y">
new Schema("foo") // => Schema<"foo">
上面的 class 实现不是这种情况(它 return 在提供数组时是 Schema<string[]>
类型的对象)。
但是如果我这样定义我的class
class Schema<T extends "foo" | string> {
constructor(public value: T[]) {}
}
我失去了呼叫 new Schema("foo")
的选项。
有什么打字功夫可以解决这个问题吗?
这里有最简单的方法:
class Schema<Value extends string, Values extends string[]> {
constructor(value: Value | [...Values]) { }
}
// What I would like to have
new Schema(["x", "y"]) // Schema<string, ["x", "y"]>
new Schema("foo") // Schema<"foo", string[]>
正如您已经注意到的,额外的 string
或 string[]
泛型存在问题。
我认为我们可以做得更好。
因为 constructor
不允许我们使用泛型,我们可以创建额外的 method
用于推理目的。
class Schema {
register<Value extends string>(value: Value): asserts this is { value: Value }
register<Value extends string[]>(value: [...Value]): asserts this is { value: Value[number] }
register<Value extends string | string[]>(value: Value): asserts this is { value: Value } {
}
}
const result: Schema = new Schema();
result.value // expected error
result.register(['x', 'y']);
result.value // x | y
Here you can find docs about asserts
and here 关于函数重载。
请告诉我它是否适合您以及是否需要改进。谢谢