You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript如何标注原地修改输入参数类型的函数类型

解决方案

方案1:使用TS内置的asserts类型谓词

TS 3.7版本引入的asserts类型谓词就是专门为这种原地修改入参类型的场景设计的,你可以直接修改process函数的返回值类型标注,告诉TS:只要这个函数正常执行完成没有抛出异常,传入的raw参数就一定是Processed类型。
修改后的代码如下:

interface Raw {
    created: string;
}
interface Processed {
    created: Date;
}

// 标注函数执行后入参raw会被收窄为Processed类型
export function process(raw: Raw): asserts raw is Processed {
    (raw as unknown as Processed).created = new Date(raw.created);
}

function printSeconds(r: Raw): void {
    process(r);
    // 此处TS会自动将r的类型收窄为Processed,不会报编译错误
    console.log(r.created.getSeconds());
}

这种方案不需要额外的类型断言,也不会产生任何运行时开销,完全符合你原地修改的需求。

方案2:适配数组map场景的重载写法

如果你需要在map等数组方法中使用process函数,单独的asserts签名无法满足需求(map需要函数有返回值),你可以给process函数加一个重载签名,类型上假装返回处理后的对象,实际还是返回原对象,完全没有拷贝开销:

// 直接调用时的原地修改签名
export function process(raw: Raw): asserts raw is Processed;
// 用于map调用的签名,实际返回原对象无拷贝
export function process(raw: Raw): Processed;
export function process(raw: Raw): Processed | void {
    (raw as Processed).created = new Date(raw.created);
    // 直接返回原对象,无内存拷贝
    return raw as Processed;
}

// 使用示例
const rawArr: Raw[] = [{created: '2024-01-01'}];
// 直接得到Processed[]类型,无需额外断言
const processedArr = rawArr.map(process);

注意事项

这种标注方式的正确性需要你自己保障:TS不会检查函数内部逻辑是否真的完成了类型转换,只会信任你写的类型签名。如果你函数内部逻辑没有完成转换,会出现运行时类型错误。

内容的提问来源于stack exchange,提问作者ocket8888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 09:54:03