【发布时间】:2020-05-04 18:17:05
【问题描述】:
我正在创建一个包装函数,它将refs 属性传递给send 函数,如下所示。用于创建我的状态机的事件类型被定义为基本接口{ refs: NodeRefs } 和可能的事件对象的联合之间的交集,例如{ type: "EVENT_1" } | { type: "EVENT_2", context: MyContextType }.
包装函数(示例代码中的useMachine)应该返回我们更新的send 函数,该函数需要一个省略refs 键的事件对象。在此处使用 Omit 会导致在尝试将我的发送函数与联合类型中的任何非共享属性一起使用时出现错误,并且我不是 100% 清楚为什么或如何以不同的方式进行操作。
enum States {
Unchecked = "UNCHECKED",
Checked = "CHECKED",
Mixed = "MIXED"
}
enum Events {
Toggle = "TOGGLE",
Set = "SET",
UpdateContext = "UPDATE_CONTEXT"
}
// Events for the state machine will be a union type a la TEvent, but all events
// will need a `refs` property. We just won't need to explicitly pass refs in
// our event calls thanks to the useMachine hook below
interface EventBase {
refs: NodeRefs;
}
type TEvent = EventBase &
(
| { type: Events.Toggle }
| {
type: Events.Set;
state: States;
}
| {
type: Events.UpdateContext;
context: Partial<Context>;
}
);
function useMachine(stateMachine: SomeStateMachine, refs: ReactRefs) {
let [currentState, setCurrentState] = useState(stateMachine.initialState);
/* ... */
// I want to omit the refs property from our event here because we are always
// sending the same values in each event, but this is triggering the error
// in our send function below.
function send(event: Omit<TEvent, "refs">) {
let nodes = Object.keys(refs).reduce(nodeReducer);
service.send({ ...event, refs: nodes });
}
return [currentState, send];
}
function MyComponent({ disabled }) {
let inputRef = useRef<HTMLInputElement | null>(null);
let [currentState, send] = useMachine(myStateMachine, { input: inputRef });
useEffect(() => {
send({
type: Events.UpdateContext,
// Error: Object literal may only specify known properties, and 'context'
// does not exist in type 'Pick<TEvent, "type">'.
context: { disabled }
});
}, [disabled]);
/* ... */
}
type NodeRefs = {
input: HTMLInputElement | null;
};
type ReactRefs = {
[K in keyof NodeRefs]: React.RefObject<NodeRefs[K]>;
};
【问题讨论】:
标签: typescript typescript-typings typescript-generics