Kiểu nhập liệu trình biên dịch typecript với generic
Tôi cố gắng đạt được một isEventOfTypechức năng chung . Ở nhiều nơi, các sự kiện từ một máy tiểu bang x-state được xác định (xem Maschine1Events, Maschine2Events). Khi xử lý sự kiện, trạng thái x chỉ có thể cung cấp một Maschine1Eventshoặc Maschine2Eventsnhưng không thể cho biết chính xác sự kiện nào được xử lý.
Do đó, tôi cần một phương pháp để kiểm tra xem sự kiện có thuộc loại mà tôi mong đợi hay không. Ví dụ: sự kiện 'CHANGE' được cung cấp.
Ví dụ này có đầy đủ chức năng, nhưng điều tôi không hiểu là tại sao bên trong fWithoutGenerichàm, các kiểu không thể được suy luận.
export type Event<TType, TData = unknown> = { type: TType } & TData;
export type Value<TType> = { value: TType };
type Maschine1Events = Event<'INC'> | Event<'DEC'> | Event<'CHANGE', Value<number>>;
type Maschine2Events = Event<'INC', Value<number> | Event<'SEND_MESSAGE', Value<string>>;
type EventTypes<T extends Event<unknown>> = T['type'];
type EventOfType<T extends Event<unknown>, U extends EventTypes<T> = EventTypes<T>> = Extract<T, { type: U }>;
function isEventOfType<T extends Event<unknown>, U extends EventTypes<T> = EventTypes<T>>(
event: T,
type: U
): event is EventOfType<T, U> {
return event.type === type;
}
function fWithGenerics(event: Maschine1Events) {
if (isEventOfType<Maschine1Events, 'CHANGE'>(event, 'CHANGE')) {
const a: Event<'CHANGE', Value<number>> = event;
}
}
function fWithOutGenerics(event: Maschine2Events) {
if (isEventOfType(event, 'SEND_MESSAGE')) {
const a: Event<'SEND_MESSAGE', Value<string>> = event; //Why can't this be infered
}
}
Liên kết sân chơi đến mã
Trả lời
Tôi muốn đưa ra isEventOfType()chữ ký sau:
function isEventOfType<E extends { type: string }, T extends E['type']>(
event: E,
type: T
): event is Extract<E, { type: T }> {
return event.type === type;
}
Tôi đã đơn giản hóa các tham số một chút và loại bỏ các mặc định tham số chung cho tham số thứ hai. Tôi không biết mục đích của chúng là gì, nhưng trừ khi bạn cần chúng, chúng có lẽ chỉ là một sự đánh lạc hướng.
Sự thay đổi lớn ở đây là các Eloại các eventthông số hiện đang bị hạn chế để {type: string}thay {type: unknown}. Các stringcung cấp cho các trình biên dịch một gợi ý để suy ra một chuỗi loại đen cho kiểu Tcủa typetham số (xem microsoft / nguyên cảo # 10.676 để biết chi tiết về về cách suy luận của các loại đen xảy ra).
Bây giờ mã hoạt động như bạn mong đợi, tôi nghĩ:
function m1(event: Maschine1Events) {
if (isEventOfType(event, 'CHANGE')) {
event.value.toFixed(2); // okay
} else {
event // {type: "INC"} | {type: "DEC"}
}
}
function m2(event: Maschine2Events) {
if (isEventOfType(event, 'SEND_MESSAGE')) {
event.value.toUpperCase(); // okay
} else {
event.value.toFixed(2); // okay
}
}
Liên kết sân chơi đến mã