如何将TypeScript函数的Number参数收窄为字面量类型并约束参数一致性?
问题:强制函数两个参数的id值类型一致
我需要编写一个方法,要求满足:
- 第一个参数为
id: number类型 - 第二个参数是
Partial<MyData>对象,必须包含id属性,且其值与第一个参数的id完全相同
我的初步实现代码如下:
type MyData = {id: number} function update<K extends MyData['id']>(id: K, newValues: Partial<MyData> & {id: K}): MyData { throw 'not implemented' } // 预期此处会报错,但实际未触发类型检查 update(3, {id: 4})
奇怪的现象
IntelliSense的提示逻辑符合预期,但实际代码并未强制执行约束。不过如果将IntelliSense提示的类型单独提取出来使用,就能得到正确的错误提示:
type ArgType = Partial<MyData> & {id: 3} const argProof: ArgType = {id: 4} // 此处报错,符合预期
请问如何修改该函数,才能实现所需的类型约束效果?
解决方案
问题根源在于TypeScript的类型推断逻辑:当传入update(3, {id:4})时,TS会将泛型K推断为宽泛的number类型(而非字面量类型3),导致约束失效。要解决这个问题,需要让TS优先推断第一个参数的字面量类型,而非宽泛的number。
方案1:调用时使用const断言强制字面量类型
type MyData = {id: number} function update<K extends MyData['id']>(id: K, newValues: Partial<MyData> & {id: K}): MyData { throw 'not implemented' } // 给第一个参数添加const断言,强制推断为字面量类型3 update(3 as const, {id: 4}) // 此处触发报错,符合预期
方案2:修改泛型定义,引导TS自动推断字面量类型
通过调整泛型参数的约束,让TS优先推断字面量类型:
type MyData = {id: number} function update<K extends number>(id: K, newValues: Partial<MyData> & {id: K}): MyData { throw 'not implemented' } update(3, {id: 4}) // 此处触发报错,符合预期
如果需要严格绑定MyData['id']的类型(避免后续MyData['id']类型变更时出现问题),可以使用K & {}的小技巧引导字面量推断:
type MyData = {id: number} function update<K extends MyData['id']>(id: K & {}, newValues: Partial<MyData> & {id: K}): MyData { throw 'not implemented' } update(3, {id: 4}) // 此处触发报错,符合预期
内容的提问来源于stack exchange,提问作者stackoverfloweth
相关产品推荐
相关产品推荐

