首页 > 解决方案 > 正确键入 MobX 的 React/Typescript 输入组件

问题描述

我想用 Typescript for MobX 编写一个 React Input 组件,它作为它的输入道具:

打字稿应该强制它stateObject[stateKey]是字符串类型的。也就是说,ExtraProps 应该在下面的示例中处理什么。但是,我无法让类型按照我期望的方式编译,但是得到

TS2322:类型 'string' 不能分配给类型 'K extends K ?字符串:任何'。

在此处查看我的相关 SO 帖子

所以以下是我的方法:

import React, {ChangeEvent, Component, InputHTMLAttributes} from "react";

type ExtraProps<T extends string | number | symbol, K extends T> = {
    stateKey: K,
    stateObject: { [k in T]: k extends K ? string : any }
}
type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange">
type InputPropType<T extends string | number | symbol, K extends T> = InputProps & ExtraProps<T, K>

export class InputField<T extends string | number | symbol, K extends T> extends Component<InputPropType<T, K>, any> {
    constructor(props: InputPropType<T, K>) {
        super(props);
        this.onChange = this.onChange.bind(this)
    }

    onChange(event: ChangeEvent<HTMLInputElement>) {
        let val: K extends K ? string : any = event.target.value; // TS2322: Type 'string' is not assignable to type 'K extends K ? string : any'.
        this.props.stateObject[this.props.stateKey] = val;
    }

    render() {
        let {stateKey, stateObject, ...props} = this.props;
        return <input {...props} value={stateObject[stateKey]} onChange={this.onChange}/>
    }
}

现在我的问题是:

同样,我想要的是一个托管输入组件,它只是从 mobx 存储读取/写入其值。

标签: typescriptmobx-reactconditional-types

解决方案


你需要这样的东西:

// TypeScript Voodoo. See:
// https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c
// for details about how this works.
export type FilterFlags<Base, Condition> = { [Key in keyof Base]: Base[Key] extends Condition ? Key : never };
export type AllowedNames<Base, Condition> = FilterFlags<Base, Condition>[keyof Base];

用法是:


type ExtraProps<T> = AllowedNames<T, string>;
type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange">
// not really sure about this, but I don't think the original '&' makes sense:
type InputPropType<T> = InputProps | ExtraProps<T>;

它为您提供了一个联合类型,其中包含 type 的字符串属性列表K。您不需要 type K,您只需要 type T,这是您的stateObject值的类型。


推荐阅读