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

React-hook-form类型错误:`addresses.${string}.street`无法赋值给Path<TFieldValues>

React Hook Form中name属性类型不匹配Path<TFieldValues>的问题解析

问题代码

import React from "react"
import { z } from "zod"
import { Control, Controller } from "react-hook-form" 

export const address = z.object({
    street: z.string(),
})

type FieldValues<TPrefix extends string> = {
    addresses: {
        [k in TPrefix]: z.infer<typeof address>
    }
}

export type AddressProperties<
    TFieldValues extends FieldValues<TPrefix>,
    TPrefix extends string = string,
> = {
    control: Control<TFieldValues>
    prefix: TPrefix
}

export function Address<TFieldValues extends FieldValues<TPrefix>, TPrefix extends string>(
    properties: AddressProperties<TFieldValues>,
) {
    const { control, prefix} = properties

    return <Controller 
        control={control} 
        // Type '`addresses.${string}.street`' is not assignable to type 'Path<TFieldValues>'
        name={`addresses.${prefix}.street`}
        render={() => <input />} 
     />
}

问题

为什么name属性的类型无法赋值给Path<TFieldValues>?该如何修复这个问题?


原因

  1. 泛型约束模糊:原代码中TPrefix仅被约束为string,TypeScript无法确认它就是TFieldValues['addresses']的合法键,因此无法认定addresses.${prefix}.street是Path<TFieldValues>的有效路径。
  2. 路径类型的精确性要求:Path<T>是react-hook-form生成的精确字符串字面量联合类型,而模板字符串${string}.street生成的是宽泛的string子类,TypeScript不会自动将宽泛类型收缩为精确的路径联合类型。

修复方案

方案1:优化泛型约束+类型断言

调整泛型参数,让prefix明确关联到TFieldValues['addresses']的键,再用类型断言确认路径合法性:

import React from "react"
import { z } from "zod"
import { Control, Controller, Path } from "react-hook-form" 

export const address = z.object({
    street: z.string(),
})

export type AddressProperties<TFieldValues> = {
    control: Control<TFieldValues>
    // 约束prefix是addresses的键且类型为string
    prefix: keyof TFieldValues['addresses'] & string
}

// 约束TFieldValues必须包含符合结构的addresses字段
export function Address<TFieldValues extends { addresses: Record<string, z.infer<typeof address>> }>(
    properties: AddressProperties<TFieldValues>,
) {
    const { control, prefix} = properties

    return <Controller 
        control={control} 
        name={`addresses.${prefix}.street` as Path<TFieldValues>}
        render={() => <input />} 
     />
}

方案2:精确泛型推断(无需断言)

通过定义更明确的类型结构,让TypeScript自动推断合法路径:

import React from "react"
import { z } from "zod"
import { Control, Controller, Path } from "react-hook-form" 

export const addressSchema = z.object({
    street: z.string(),
})

type AddressType = z.infer<typeof addressSchema>

// 明确FieldValues的结构要求
type AddressFieldValues = {
    addresses: Record<string, AddressType>
}

export type AddressProperties<TFieldValues extends AddressFieldValues> = {
    control: Control<TFieldValues>
    prefix: keyof TFieldValues['addresses']
}

export function Address<TFieldValues extends AddressFieldValues>(
    { control, prefix }: AddressProperties<TFieldValues>,
) {
    const fieldName = `addresses.${prefix}.street` as Path<TFieldValues>

    return <Controller 
        control={control} 
        name={fieldName}
        render={() => <input />} 
     />
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:44:58