typescript - 为什么这个递归类型定义需要定义原语?
问题描述
如果我删除了这种类型的注释行,为什么不能编译?
type DeepPartial<T> =
T extends Array<any> ? T
: T extends ReadonlyArray<any> ? T
: T extends Function ? T
: T extends number ? T // why is this needed
: T extends string ? T // same thing...
: T extends boolean ? T // same thing...
: T extends bigint ? T // same thing...
: T extends symbol ? T // same thing...
: T extends object ? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
function test<T>(o: DeepPartial<T>) {
if (o === 1) return 0;
if (o === '') return 1;
if (o === false) return 2;
if (o === 1n) return 3;
if (o === Symbol.hasInstance) return 4;
if (typeof o === 'number' && o === 2) return 5; //or this needed?
return 6;
}
我认为 DeepPartial 类型上的注释行应该是不必要的,因为最终条件但编译器不同意(Playground Link)。
解决方案
具体的错误信息是
此条件将始终返回 'false',因为类型 'DeepPartial<T>' 和 '[number|string|boolean|bigint|symbol]' 没有重叠。
这与您if
在将函数定义为时得到的所有错误消息非常相似,但最后一条语句除外function test<T>(o: T)
:
此条件将始终返回 'false',因为类型 'T' 和 '[number|string|boolean|bigint|symbol]' 没有重叠。
因为没有先区分类型,所以T
type 在 的体内是不透明的类型test()
,所以必须像对待unknown
而不是对待any
。
引用类型的非同质混合并不典型T
,所以如果这是您需要的,这可能是我建议的方法:
const enum Test {
ONE,
STRING,
FALSE,
BIG_ONE,
HAS_INSTANCE,
TWO,
UNKNOWN
}
type TestMap<T> = T extends 1 ? Test.ONE
: T extends '' ? Test.STRING
: T extends false ? Test.FALSE
: T extends 1n ? Test.BIG_ONE
: T extends SymbolConstructor['hasInstance'] ? Test.HAS_INSTANCE
: T extends 2 ? Test.TWO
: Test.UNKNOWN;
function test<T>(o: T): TestMap<T> {
function testImpl(o: any): Test {
if (o === 1) return Test.ONE;
if (o === '') return Test.STRING;
if (o === false) return Test.FALSE;
if (o === 1n) return Test.BIG_ONE;
if (o === Symbol.hasInstance) return Test.HAS_INSTANCE;
if (o === 2) return Test.TWO;
return Test.UNKNOWN;
}
return testImpl(o) as TestMap<T>;
}
推荐阅读
- javascript - 事件侦听器在上下文中工作,但不是在另一个上下文中工作 - 代码相同,并且没有观察到错误。可能的原因?
- excel - 错误“无法获取 WorksheetFunction 类的 VLookup 属性”背后的原因可能是什么?
- java - 尝试将用户签名到服务器主机时如何解决“字符串无法转换为 json 对象”错误?
- influxdb - 2200万点的慢查询
- java - 如何在同一台机器上运行数百个 Kafka 消费者?
- lucene - Hibernate Search 手动索引抛出“org.hibernate.TransientObjectException:实例未与此会话关联”
- vba - 为什么我需要 Int 函数
- docker-compose - 将现有卷附加到 docker 容器
- sql-server - SQL Server 时间数据类型与 Excel 不兼容?
- php - 将查询 LEFT JOIN 更改为 FULL OUTER JOIN(尊重空值) - 如何更改它(之后没有可怕的性能)?