如何将 e
的类型推断为 React.ChangeEvent<HTMLInputElement>
。
完整代码:
import React, { useState, useCallback } from 'react';
import produce from 'immer';
type RestTuple<T extends [any, ...any[]]> = T extends [any, ...infer R] ? R : never;
function useImmer<S>(initialState: S | (() => S)) {
const [s, ss] = useState(initialState);
const immer = useCallback(<F extends (s: S, ...es: any[]) => any>(fn: F) => (...es: RestTuple<Parameters<F>>) =>
produce(s, s => {
fn(s as S, ...es);
}),
[s]
);
return [s, immer, ss] as const;
}
export function MyComponent() {
const [user, set_user] = useImmer({ name: 'xialvjun', age: 30 });
return (
<div>
<input type="text" value={user.name} onChange={set_user((u, e) => (u.name = e.target.value))} />
</div>
);
}
答案 0 :(得分:1)
您的 RestTuple
条件类型阻止编译器根据上下文推断回调参数,因为它需要通过 RestTuple
的定义“向后”进行推断。
相反,我倾向于使您的函数仅在元组类型 T
中通用,如下所示:
function useImmer<S>(initialState: S | (() => S)) {
const [s, ss] = useState(initialState);
const immer = useCallback(<T extends any[]>(fn: (s: S, ...es: T) => void) =>
(...es: T) =>
produce(s, s => {
fn(s as S, ...es);
}),
[s]
);
return [s, immer, ss] as const;
}
那么你的电话似乎表现得更好:
export function MyComponent() {
const [user, set_user] = useImmer({ name: 'xialvjun', age: 30 });
return (
<div>
<input type="text" value={user.name} onChange={
set_user((u, e) => (u.name = e.target.value))} />
</div>
);
}
如果将鼠标悬停在 IDE 中,您会看到 e
现在根据需要推断为 React.ChangeEvent<HTMLInputElement>
。