我想要一个通用钩子,为特定的 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];
}
答案 0 :(得分:3)
定义状态形状要容易一些,然后将钩子限制为仅接受具有相应有效值的有效状态键:
type State = { [Properties.title]: string, [Properties.age]: number };
const useUpdateState = <P extends keyof State>(property: P, defaultValue: State[P]) => {
// ...