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

TypeScript:如何让内部函数参数推断为子对象键类型

问题描述

尝试基于react-hook-form的register函数封装包装函数时,遇到类型兼容问题,核心是如何约束内部函数的参数类型。示例代码如下:

interface Child1 {
    p1: string;
}

interface Child2 {
    p2: number
}

interface Parent {
    child1: Child1;
    child2: Child2
}

function register(o: "child1.p1" | "child2.p2") {return {}}

function getChildRegister(parent: Parent, parentKey: keyof Parent) {
    return function(childKey: keyof Parent[typeof parentKey]) {
        return register(`${parentKey}.${childKey}`)
    }
}

const p: Parent = {child1: {p1: ""}, child2: {p2: 1}}

const result = getChildRegister(p, "child1")("p1") // 报错!内部函数参数未正确推断

传入"child1"后,期望内部函数参数能接受Child1的键(即p1),但TypeScript仅允许传入string类型,需要让内部函数正确推断子对象的键类型。

解决方案

问题根源在于getChildRegister未通过泛型固定parentKey的具体类型,导致TypeScript无法在返回的内部函数中精确推导子对象的键类型。通过添加泛型参数约束parentKey的类型即可解决:

interface Child1 {
    p1: string;
}

interface Child2 {
    p2: number
}

interface Parent {
    child1: Child1;
    child2: Child2
}

function register(o: "child1.p1" | "child2.p2") {return {}}

// 添加泛型K,约束为keyof Parent的子集
function getChildRegister<K extends keyof Parent>(parent: Parent, parentKey: K) {
    // 此时Parent[K]为对应子对象的精确类型,keyof Parent[K]即子对象的键集合
    return function(childKey: keyof Parent[K]) {
        // 用模板字面量类型做类型断言,让TypeScript识别拼接后的字符串符合register的参数要求
        return register(`${parentKey}.${childKey}` as `${K}.${keyof Parent[K]}`)
    }
}

const p: Parent = {child1: {p1: ""}, child2: {p2: 1}}

const result = getChildRegister(p, "child1")("p1") // 正常工作,参数仅接受"p1"

关键说明:

  • 泛型K extends keyof Parent固定了parentKey的具体类型,让TypeScript能追踪到对应子对象的类型
  • 内部函数的childKey类型设为keyof Parent[K],自动匹配当前子对象的所有键
  • 模板字面量类型断言确保拼接后的参数与register的联合类型参数兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:21