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

TypeScript递归类型与可选属性兼容问题求助

解决TypeScript中带可选属性对象的StatePath类型失效问题

原类型定义

以下是用于通过字符串/索引数组导航对象或嵌套数组的TypeScript类型:

export type PredicateFunction<ArrayType> = (array: ArrayType, index?: number) => boolean;
export type IndexOrPredicateFunction<Type> = number | PredicateFunction<Type>;
export type StatePathKey = IndexOrPredicateFunction<any> | string;

export type StatePath<Obj, Path extends (string | IndexOrPredicateFunction<any>)[] = []> =
    object extends Obj
        ? Path
        : Obj extends object
            ? (Path |
                    // 检查对象是否为数组
                    (Obj extends readonly any[] ?
                        // 数组仅允许索引或断言函数
                        StatePath<Obj[number], [...Path, IndexOrPredicateFunction<Obj[number]>]>
                        // 对象则生成所有可能键的类型
                        : { [Key in string & keyof Obj]: StatePath<Object[Key], [...Path, Key]> }[string & keyof Obj]))
            : Path;

正常工作场景

当使用不含可选属性的接口State1时,该类型可以正常推导路径:

interface State1  {
    test: {
        nestedTest: boolean
    }
}
const t1: StatePath<State1> = ['test', 'nestedTest']; // 类型检查通过

问题场景

当接口包含可选属性(如State2)时,该类型无法正确推导可选属性的路径,赋值操作会报错:

interface State2  {
    test: {
        nestedTest?: boolean
    }
}
// 无法将 ['test', 'nestedTest'] 赋值给 StatePath<State2>

解决方案

修正后的类型定义如下,解决了可选属性的推导问题:

export type PredicateFunction<ArrayType> = (array: ArrayType, index?: number) => boolean;
export type IndexOrPredicateFunction<Type> = number | PredicateFunction<Type>;
export type StatePathKey = IndexOrPredicateFunction<any> | string;

export type StatePath<Obj, Path extends (string | IndexOrPredicateFunction<any>)[] = []> =
    object extends Obj
        ? Path
        : Obj extends null | undefined // 处理null/undefined分支,避免推导中断
            ? Path
            : Obj extends object
                ? (Path |
                        // 数组类型处理逻辑不变
                        (Obj extends readonly any[] ?
                            StatePath<Obj[number], [...Path, IndexOrPredicateFunction<Obj[number]>]>
                            // 修复笔误+处理可选属性:取属性的非undefined类型进行推导
                            : { [Key in string & keyof Obj]: StatePath<NonNullable<Obj[Key]>, [...Path, Key]> }[string & keyof Obj]))
                : Path;

修正说明

  • 修复核心笔误:将Object[Key]改为Obj[Key],避免错误引用全局Object类型。
  • 添加null/undefined分支处理:当属性值为null或undefined时终止路径推导,避免类型崩溃。
  • 可选属性处理:使用NonNullable<Obj[Key]>提取可选属性的实际类型,忽略undefined分支,确保路径可以深入到可选属性内部。

验证修正效果

修正后,带可选属性的接口可以正常推导路径:

interface State2  {
    test: {
        nestedTest?: boolean
    }
}
const t2: StatePath<State2> = ['test', 'nestedTest']; // 类型检查通过

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 09:35:58