TypeScript中如何约束接口部分属性且保留变量具体类型?
问题描述
我定义了如下接口I:
interface I { // 问题:我仅关心约束输入参数 fn: (s: string) => any val: any }
我的目标是仅断言:
val属性存在,不约束其类型fn是接收string类型参数的函数,不约束其返回值类型
使用示例如下:
const noice = { fn: (s: string) => s.length, val: new Date() } const test1: I = noice test1.fn // (property) I.fn: (s: string) => any test1.val // (property) I.val: any noice.fn // (property) fn: (s: string) => number noice.val // (property) val: Date
我想去掉any,让test1拥有和noice相同的具体类型。请问可以用satisfies关键字吗?对于未升级到4.9版本的情况以及旧代码该如何处理?
解决方案
TypeScript 4.9+ 使用satisfies关键字
完全可以用satisfies,它的核心作用就是检查值是否符合某个类型约束,但保留值本身的具体类型,正好匹配你的需求。
修改后的代码如下:
interface I { fn: (s: string) => unknown // 用unknown替代any更安全,不影响约束效果 val: unknown } const noice = { fn: (s: string) => s.length, val: new Date() } const test1 = noice satisfies I; test1.fn // (property) fn: (s: string) => number test1.val // (property) val: Date
这里把any换成unknown是更规范的写法,因为unknown是类型安全的顶级类型,不会像any那样绕过类型检查,同时依然能满足“仅约束存在性和fn的参数类型”的需求。
旧版本(TypeScript <4.9)的处理方案
如果无法升级TS版本,可以用泛型工具类型来实现类似效果:
方案1:泛型接口+类型约束
定义一个带泛型的接口,同时通过extends约束泛型符合你的要求:
interface I<TFnReturn, TVal> { fn: (s: string) => TFnReturn val: TVal } const noice = { fn: (s: string) => s.length, val: new Date() } // 方式1:手动指定泛型参数 const test1: I<ReturnType<typeof noice.fn>, typeof noice.val> = noice; // 方式2:工具函数自动推导类型 function assertI<T extends I<unknown, unknown>>(val: T): T { return val; } const test2 = assertI(noice); test1.fn // (property) fn: (s: string) => number test1.val // (property) val: Date test2.fn // (property) fn: (s: string) => number test2.val // (property) val: Date
方案2:类型谓词(Type Predicate)
用类型守卫验证值符合约束,同时保留原类型,还能兼顾运行时检查:
interface I { fn: (s: string) => unknown val: unknown } function isI<T>(val: T): val is T & I { return typeof val === 'object' && val !== null && typeof (val as any).fn === 'function' && 'val' in val; } const noice = { fn: (s: string) => s.length, val: new Date() } if (isI(noice)) { const test1 = noice; test1.fn // (property) fn: (s: string) => number test1.val // (property) val: Date }
内容的提问来源于stack exchange,提问作者user13203487
相关产品推荐
相关产品推荐

