TypeScript-仅允许类型、文字和实例的类型约束
由于TypeScript的主动类型擦除,即类型注释、接口、类型和泛型类型参数都被编译器擦除,因此很难对某些类型约束建模。下面是我尝试建模的示例,以及我迄今为止成功实现的示例 参数必须是类型本身,而不是类型的实例或文本 这可以通过引入TypeScript-仅允许类型、文字和实例的类型约束,typescript,Typescript,由于TypeScript的主动类型擦除,即类型注释、接口、类型和泛型类型参数都被编译器擦除,因此很难对某些类型约束建模。下面是我尝试建模的示例,以及我迄今为止成功实现的示例 参数必须是类型本身,而不是类型的实例或文本 这可以通过引入类型来解决,如下所示 type Type<T = any> = { new(...args: any[]): T; readonly prototype: T; readonly name: string; } 参数必须是实例或
类型来解决,如下所示
type Type<T = any> = {
new(...args: any[]): T;
readonly prototype: T;
readonly name: string;
}
参数必须是实例或文字,而不是类型本身
这不是那么琐碎,到目前为止我还没能解决这个问题。给定以下函数定义
function fn(p: String) { ... }
fn("") // okay - it's a String literal
fn(new String()) // okay - it's a String instance
fn(String) // not okay - it's the String type
这很好,但当您想允许任何文字或实例,但不允许任何类型时,它就会中断
function fn(p: Object) { ... }
fn("") // okay - it's a String literal
fn(123) // okay - it's a Number literal
fn(new String()) // okay - it's a String instance
fn(String) // okay, BUT should be disallowed because it's the String type.
function fn(p: InstanceOrLiteral) { ... }
fn("") // okay - it's a String literal
fn(new String()) // okay - it's a String instance
fn(123) // okay - it's a Number literal
fn(String) // not okay - it's the String type
fn(Object) // not okay - it's the Object type
fn(Number) // not okay - it's the Number type
我不确定第二个问题是否可以解决,但是我想要与类型一致的东西,但正好相反;例如
type InstanceOrLiteral<T = any> = {
// what goes here?
}
function fn(p: InstanceOrLiteral<String>) { ... }
fn("") // okay - it's a String literal
fn(new String()) // okay - it's a String instance
fn(123) // not okay - it's a Number literal
fn(String) // not okay - it's the String type
后者可能吗
fn(String)//好的,但是应该被禁止,因为它是字符串
类型
不,它的StringConstructor
类型。至少typescript和intellisense是这么说的
这对你有用吗
功能fn(p:K){
}
您的第一个问题可以通过使用条件类型来解决
type InstanceOrLiteral<T, WhatInstancesAreDisallowed = unknown> =
T extends { new(): WhatInstancesAreDisallowed } ? never : T
你的第二期需要一些技巧。您不能简单地将条件类型中的T
设置为可选,并默认设置为unknown
(=union of all type=>将始终匹配条件类型)或any
(=禁用键入=>将导致条件类型的两个选项合并never | T
,其解析为仅T
=>因此也不符合您的要求)。相反,您必须推断函数调用的给定类型,并将其传递到InstanceOrLiteral
类型。这样,条件类型可以与实际给定类型一起工作
function fn2<T>(p: T & InstanceOrLiteral<T>) { }
fn2("") // okay - it's a String literal
fn2(new String()) // okay - it's a String instance
fn2(123) // okay - it's a Number literal
fn2(String) // not okay - it's the String type
fn2(Object) // not okay - it's the Object type
fn2(Number) // not okay - it's the Number type
函数fn2(p:T&InstanceOrLiteral){
fn2(“”//好的-它是一个字符串文本
fn2(new String())//好的-这是一个字符串实例
fn2(123)//好的-这是一个数字文字
fn2(字符串)//不正常-这是字符串类型
fn2(对象)//不正常-这是对象类型
fn2(数字)//不正常-这是数字类型
这将适用于字符串|数字文本和实例,但不适用于任何实例或文本。本质上,约束应该是类型的完全反转,所以这就像说,除了类型之外的任何内容。因此,您的示例需要类似于函数fn(p:K){…}
这很有效。有没有办法禁止InstanceOrLiteral
,因为它仍然允许类型?(在配置中不使用“no any”)@MatthewLayton遗憾的是,使用这种方法,条件类型需要特定给定参数的类型信息。我想不出任何其他方法。好的,dokey。这仍然是一个很好的解决方案,因此在此基础上,我接受!
type InstanceOrLiteral<T, WhatInstancesAreDisallowed = unknown> =
T extends { new(): WhatInstancesAreDisallowed } ? never : T
function fn(p: InstanceOrLiteral<String>) {}
fn("") // okay - it's a String literal
fn(new String()) // okay - it's a String instance
fn(123) // not okay - it's a Number literal
fn(String) // not okay - it's the String type
function fn2<T>(p: T & InstanceOrLiteral<T>) { }
fn2("") // okay - it's a String literal
fn2(new String()) // okay - it's a String instance
fn2(123) // okay - it's a Number literal
fn2(String) // not okay - it's the String type
fn2(Object) // not okay - it's the Object type
fn2(Number) // not okay - it's the Number type