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

TypeScript访问映射Proxy对象时键类型丢失特异性的解决问询

问题:如何阻止索引签名中的key被拓宽为string?

基础示例问题

能否阻止key被拓宽为string?

type Foo = {
  [key in string]: key
}
type Test = Foo['bar']
//   ^? type Test = string

如何让Test的类型为'bar'而非string?


实际场景背景

我正在为API访问用的Proxy定义类型。该API部分端点预先已知,部分未知,因此Proxy需要同时支持已知字符串(如'a' | 'b' | 'c')和任意未知字符串(string)。

先定义已知端点的schema:

type Paths = {
    '/a/b/{id}': {}
    'foo/bar': {}
}

还有一个推断URL动态部分的类型工具:

type ExtractParams<url extends string> = 
    url extends `${string}{${infer A extends string}}${string}`
        ? {[param in A]: string}
        : {}

type test = ExtractParams<'/a/b/{foo}'>
//   ^? type test = { foo: string }

我最初为Proxy编写的类型如下:

type MyProxy = {
    [key in keyof Paths]: ExtractParams<key>
} & {
    [key in string]: ExtractParams<key>
}

这个类型允许访问任意字符串:

MyProxy['/a/b/{id}'] // 已知端点,正常
MyProxy['/la/la/la'] // 未知端点,正常

但问题在于,TypeScript无法正确推断未知端点的动态部分——因为[key in string]中的key会被简化为string,而非保留具体字符串值:

type knownPathParam = MyProxy['/a/b/{id}']
//   ^? type knownPathParam = { id: string } <-- 正确

type unknownPathParam = MyProxy['/d/e/{id}']
//   ^? type unknownPathParam = {}           <-- 错误,期望为{ id: string }

正如基础示例所示,ExtractParams单独使用时正常,但放到[key in string]索引签名中后,key会被拓宽为string:

type BasicDemo = {
    [key in string]: key
}

type test = BasicDemo['some specific string']
//   ^? type test = string

有没有办法让key保留被访问时的特定字符串类型?


解决方案

常规索引签名会统一将key视为string,无法保留具体字面量信息。要解决这个问题,需要用泛型+条件类型替代索引签名,让TypeScript保留传入的具体字符串类型:

方案1:泛型索引类型

直接将MyProxy定义为泛型,通过条件分支适配已知/未知路径:

type MyProxy<K extends string = string> = 
    K extends keyof Paths 
        ? ExtractParams<K> 
        : ExtractParams<K>

// 使用示例
type knownPathParam = MyProxy<'/a/b/{id}'> // { id: string }
type unknownPathParam = MyProxy<'/d/e/{id}'> // { id: string }
type anyPath = MyProxy // 对应任意string的类型,即{}

方案2:模拟Proxy的get签名(更贴合实际场景)

如果要模拟Proxy的类型结构,可通过接口的get方法签名实现:

interface MyProxy {
    get<K extends string>(key: K): K extends keyof Paths ? ExtractParams<K> : ExtractParams<K>
}

核心原理

泛型会保留传入的具体字符串字面量类型,让ExtractParams能直接接收该字面量进行解析,而非接收被拓宽后的string类型,从而正确推断出URL中的动态参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:47:50