typescript - Fonksiyon çağrılarının haritasını yazma
ACTIONS_MAP kullanılarak çağrılan bir fonksiyonu yazmakta sorun yaşıyorum. ACTIONS_MAP[action.type](action); satırında "Çağrı imzası olmayan bir ifade çağrılamaz." hatası alıyorum.
Bence olan şu ki, fetchAction, navigateAction ve openModalAction her biri kendi türünde bir action argümanı bekliyor. Bu yüzden derleme sırasında TS, her bir action fonksiyonuna doğru türü gönderip göndermediğimden %100 emin olamıyor.
import { fetchAction, FetchAction } from './fetch';
import { navigateAction, NavigateAction } from './navigate';
import { openModalAction, OpenModalAction } from './openModal';
const ACTIONS_MAP = {
$fetch: fetchAction,
$navigate: navigateAction,
$openModal: openModalAction,
};
export type Action =
| FetchAction
| NavigateAction
| OpenModalAction;
export function dispatchActions(actions: Action[]) {
actions.forEach(action => {
ACTIONS_MAP[action.type](action);
});
}
Bunu yazmanın bir yolu var mı yoksa bu yaklaşıma iyi bir alternatif nedir?
Düzenle: İşte fetch.ts için uydurma bir örnek, diğerleri benzerdir.
export interface FetchAction {
type: '$fetch';
// More types here
}
export function fetchAction(action: FetchAction) {
// Do some work here
}
Cevap #1
Bu durumda bir switch kullanmaktan kaçınmanın tek yolu (en azından benim aklıma gelen) bir tür belirlemesi kullanmaktır. İdeal olmasa da, bazen TypeScript kodunda tür belirlemeleri gerekli olabiliyor, ancak bunları yalnızca kesinlikle gerekli olduğunda kullanmalıyız:
type ActionHandler = (a: Action)=> void;
export function dispatchActions(actions: Action[]) {
actions.forEach(action => {
(ACTIONS_MAP[action.type] as ActionHandler)(action);
});
}
Cevap #2
Eğer işlem fonksiyonlarının kendilerine ait referansları paylaşmanıza gerek yoksa, bunu pratik bir çözüm olarak şu şekilde deneyebilirsiniz:
type FooAction = {
type: '$foo';
payload: string;
}
type BlahAction = {
type: '$blah';
payload: number;
}
type Action = FooAction | BlahAction;
function fooAction(action: FooAction) {
console.log(action.payload);
}
function blahAction(action: BlahAction) {
console.log(action.payload + 1)
}
const dispatchAction = (action: Action) => {
switch (action.type) {
case '$foo':
// TS knows action must be a FooAction
return fooAction(action);
case '$blah':
// TS knows action must be a BlahAction
return blahAction(action);
default:
return;
}
}
function dispatchActions(actions: Action[]) {
actions.forEach(action => {
dispatchAction(action);
});
}
dispatchActions([
{ type: "$foo", payload: 'bar' },
{ type: "$blah", payload: 1 }
])Bu, doğru yerlerde tip kontrolü yapmanızı sağlar (sanırım). Ancak her verilen case ifadesinden çıktığınızda tip daraltma bilgilerini kaybedersiniz. Yani fonksiyonu döndürüp sonra çağıramazsınız.
