我可以从泛型参数推断出枚举值吗?

时间:2020-05-29 12:07:58

标签: typescript

我想要什么

我想要一个通用钩子,为特定的 Pre-existing 属性创建getter / setter。我的理想实现如下:

const [getTitle, setTitle] = useUpdateState("title", "<defaultTitle>");
const [getAge, setAge] = useUpdateState("age", 44);
const [getErr, setErr] = useUpdateState("age", "44"); // Must error, as my types (defined elsewhere) state "age" must be number

替代:

const [getTitle, setTitle] = useUpdateState<TitleUpdate>("Mr");
const [getAge, setAge] = useUpdateState<AgeUpdate>(44);
const [getErr, setErr] = useUpdateState<AgeUpdate>("44"); // Must error

我有什么

但是我的当前实现要求我传入类型AND属性,以确保defaultValue的类型正确。


const [getTitle, setTitle] = useUpdateState<TitleUpdate>(Properties.title, "Mr");
const [getAge, setAge] = useUpdateState<AgeUpdate>(Properties.age, 44);
const [getErr, setErr] = useUpdateState<AgeUpdate>(Properties.age, "44"); // Must Error!

感觉类型和property都不需要。

这是我到目前为止的实现(TypeScriptPlaygroud

enum Properties {
    title = 'title',
    age = 'age',
};
type TitleUpdate = { property: Properties.title, value: string };
type AgeUpdate = { property: Properties.age, value: number };

type Update = TitleUpdate | AgeUpdate;

let state: {
    [Properties.title]: TitleUpdate['value'],
    [Properties.age]: AgeUpdate['value'],
} = {
    [Properties.title]: '',
    [Properties.age]: 0,
}

const useUpdateState = <U extends Update>(property: Properties, defaultValue: U['value']) => {
    // const property = Properties[keyof U]; // <- Want to infer this from U
    const getter = (): U['value'] => state[property];
    const setter = (value: U['value']): void => {
        state = { ...state, ...{ [property]: value } }
    };
    setter(defaultValue);
return [getter, setter];
}

1 个答案:

答案 0 :(得分:3)

定义状态形状要容易一些,然后将钩子限制为仅接受具有相应有效值的有效状态键:

type State = { [Properties.title]: string, [Properties.age]: number };

const useUpdateState = <P extends keyof State>(property: P, defaultValue: State[P]) => {
// ...

Playground