打字稿泛型类型 - 类型“keyof T1”不能用于索引类型

帕维尔·巴卡

我有验证表单的函数,我希望该函数位于一个单独的文件中,但我遇到了类型问题,因为validationRequirements[fieldName]我收到错误Type 'keyof T1' cannot be used to index type '{ name: (value: string) => boolean; }'.

这是我的验证要求:

const validationRequirements = {
    name: (value: string) => false, //mock
}

createValidationObj 接口:

interface CreateValidationObjI<T1> {
    validation: T1
    fieldName: keyof T1
    value: string
}

在这里,我调用一个函数来更新验证对象,我将其validationI作为 typescript 参数传递,然后将其用作泛型:

const onChangeValidation = ({ value, fieldName }: { value: string; fieldName: keyof typeof validation }) => {
    const validationObj = createValidationObj<validationI>({ validation, fieldName, value })
}

这是验证功能,我希望该功能分开:

const createValidationObj = <T1 extends {}>({ validation, fieldName, value }: CreateValidationObjI<T1>) => ({
    ...validation,
    [fieldName]: {
        ...validation[fieldName],
        isValid: validationRequirements[fieldName](value), <-- Type 'keyof T1' cannot be used to index type '{ name: (value: string) => boolean; }'.
        isTouched: true,
    },
})

链接到示例:示例

希瓦姆·辛格拉

问题

考虑这个代码。类型对象中的任何字段Parent都可以分配给类型对象Child(只要它们的类型匹配)。这是因为Parenthas keys "a" | "b"所以,绝对,parentObject有钥匙是childObject有但反过来是不正确的parentObject是缺少关键cchildObject

因此,简而言之,我们为其分配字段的对象的键必须是我们正在分配的对象的键的子集。

type 的键{}是一个空集,因此函数中的错误f3

interface Parent {
    a: string
    b: string
}

interface Child {
    a: string
    b: string
    c: string
}

const parentObject: Parent = {
    a: "abc",
    b: "string"
}

const childObject: Child = {
    a: "abc",
    b: "string",
    c: "string"
}

type KeysOfParent = keyof Parent // "a" | "b"
type KeysOfChild = keyof Child // "a" | "b" | "c"

function f(field: keyof Parent) {
    childObject[field] = "abc" // OK
}

function f2(field: keyof Child) {
    parentObject[field] = "abc" // ERROR
}

function f3<T extends {}>(field: keyof T) {
    parentObject[field] = "abc" // ERROR
}

游乐场

因此,在问题中,在 function 中createValidationObjfieldName具有键 -keyof {}这绝对不是validationRequirements("name")键的子集所以错误。

解决方案

如果它不违反您的要求,则完全删除T1

interface validationI {
    name: {
        isValid: boolean
        isTouched: boolean
        errorMsg: string
    },
    field2: {
        isValid: boolean
        isTouched: boolean
        errorMsg: string
    },
}

const validation: validationI = {
    name: {
        isValid: false,
        isTouched: false,
        errorMsg: "Min 3 chars",
    },
    field2: {
        isValid: false,
        isTouched: false,
        errorMsg: "Min 3 chars",
    },
}
type X = keyof typeof validation

const validationRequirements = {
    name: (value: string) => false, //mock
    field2: (value: string) => false, //mock
}

interface CreateValidationObjI<T1 extends validationI> {
    validation: T1
    fieldName: keyof T1
    value: string
}

const createValidationObj = ({validation, fieldName, value}: CreateValidationObjI<validationI>) => ({
    ...validation,
    [fieldName]: {
        ...validation[fieldName],
        isValid: validationRequirements[fieldName](value),
        isTouched: true,
    }
})

const onChangeValidation = ({ value, fieldName }: { value: string; fieldName: keyof typeof validation }) => {
    const validationObj = createValidationObj({ validation, fieldName, value })
}

游乐场

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章