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

如何实现TypeScript函数输入对象键依赖其他键值的静态类型?

TypeScript 根据字段值约束对象键的实现方案

问题描述

需要实现一个函数,其输入对象的字段需根据method的值做静态类型约束:仅当method为URL类型时允许headers字段,否则禁止该字段。同时要求函数返回值能正确推断输入的类型。当前代码无法实现该约束(传入method: 'memory'时仍能添加headers字段而不报错),希望找到比Exact类型助手更简单的解决方案。

原代码问题分析

原代码中泛型参数$Input extends Input<URL | 'memory'>的写法存在缺陷:TypeScript的结构类型系统允许包含额外属性的对象赋值给兼容类型,且泛型参数会被推断为包含额外属性的类型(如{ method: 'memory', headers: {} }),该类型仍满足extends Input<'memory'>的条件,因此无法触发错误。

简化解决方案

通过将泛型参数约束为method的类型(而非整个输入对象的类型),让TypeScript对method的每个可能分支单独做类型检查,从而实现精确约束:

export type Input<$Method extends URL | 'memory'> = {
  method: $Method
} & ($Method extends URL ? { headers?: HeadersInit } : {})

// 泛型参数约束为method的类型,输入直接使用Input<$Method>
declare const foo: <$Method extends URL | 'memory'>(input: Input<$Method>) => Input<$Method>

// 合法调用
foo({ method: new URL('http://abc'), headers: {} }) 
foo({ method: new URL('http://abc') }) 
foo({ method: 'memory' }) 

// @ts-expect-error headers字段在method为'memory'时被禁止
foo({ method: 'memory', headers:{} }) 

方案说明

  1. 类型推断逻辑:调用函数时,TypeScript会先推断$Method的具体类型(URL或'memory'),再检查输入是否匹配Input<$Method>的结构。
  2. 额外属性检查:当传入对象字面量时,若包含Input<$Method>中没有的字段(如method: 'memory'时的headers),TypeScript会触发对象字面量额外属性检查,直接报错。
  3. 返回值类型:返回值Input<$Method>会自动匹配输入的类型,确保类型推断准确。

若需要更严格的约束(比如禁止非字面量对象携带额外属性),可以结合Omit或精确类型,但上述方案已满足核心需求,且实现更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:06:01