正如你所注意到的,你不明白
string[] | number[] | Date[]
通过创建类型为
string | number | Date
(string | number | Date)[]
宽度大于
,则会出现编译器错误,因为无法扩展子类型的属性。
如果你有这样的工会
字符串|编号|日期
字符串[]|数字[]|日期[]
,您可以使用
distributive conditional types
:
type DistributeArray<T> = T extends any ? T[] : never;
然后你可以定义
TestWithType
DistributeArray
:
// no error:
interface TestWithType<T extends string | number | Date> extends Test {
values: DistributeArray<T>;
}
并验证其行为是否符合预期:
declare const testWithString: TestWithType<string>
testWithString.values; // string[]
declare const testWithDate: TestWithType<Date>
testWithDate.values; // Date[]
declare const testWithStringOrNumber: TestWithType<string | number>
testWithStringOrNumber.values; // string[] | number[]
希望有帮助。祝你好运!
编辑:
作为一个相关的问题,有没有办法禁止将联合类型传递给泛型?(如要求只指定字符串、数字或日期中的一个)
可能的
,但它需要以一种让我不舒服的方式滥用类型系统。如果你不需要的话,我建议你不要那样做。在这里:
type DistributeArray<T> = T extends any ? T[] : never;
type NotAUnion<T> = [T] extends [infer U] ? U extends any ?
T extends U ? unknown : never : never : never
type ErrorMsg = "NO UNIONS ALLOWED, PAL"
interface TestWithType<T extends (
unknown extends NotAUnion<T> ? string | number | Date : ErrorMsg
)> extends Test {
values: DistributeArray<T>
}
declare const testWithString: TestWithType<string> // okay
declare const testWithDate: TestWithType<Date> // okay
declare const testWithStringOrNumber: TestWithType<string | number> // error:
// 'string | number' does not satisfy the constraint '"NO UNIONS ALLOWED, PAL"'.
NotAUnion<T>
计算结果为
unknown
T
不是工会。。。否则它的计算结果是
never
(底部类型)。然后,在
测试类型
类型
T型
unknown extends NotAUnion<T> ? string | number | Date : ErrorMsg
,勉强避开了循环引用的规则。如果你通过了一个非工会组织
T型
,它变成
T extends string | number | Date
和以前一样。如果你通过工会,它就变成
T extends ErrorMsg
ErrorMsg
,所以开发人员应该有足够的希望了解正在发生的事情。它是有效的,但它是非常粗略的东西。不过,这是你自找的。