TypeScript ok işlevinde dönüş türünü belirtin


118

React ve Redux kullanıyorum ve arabirimler olarak eylem türleri belirlendi, böylece redüktörlerim gelişmiş tip güvenliği için etiketli birleşim türlerinden yararlanabilir.

Yani, şuna benzeyen tür bildirimlerim var:

interface AddTodoAction {
    type: "ADD_TODO",
    text: string
};

interface DeleteTodoAction {
    type: "DELETE_TODO",
    id: number
}

type TodoAction = AddTodoAction | DeleteTodoAction

Bu eylemleri oluşturan yardımcı işlevler yapmak istiyorum ve bunun için ok işlevlerini kullanma eğilimindeyim. Bunu yazarsam:

export const addTodo1 = (text: string) => ({
    type: "ADD_TODO",
    text
});

Derleyici AddTodoAction, dönüş türü açıkça belirtilmediğinden bunun geçerli olduğundan emin olmak için herhangi bir yardım sağlayamaz . Bunu yaparak dönüş türünü açıkça belirtebilirim:

export const addTodo2: (text: string) => AddTodoAction = (text: string) => ({
    type: "ADD_TODO",
    text
})

Ancak bu, işlev argümanlarımı iki kez belirtmeyi gerektirir, bu nedenle ayrıntılı ve okunması daha zordur.

Ok gösterimini kullanırken dönüş türünü açıkça belirtebilmemin bir yolu var mı?

Bunu denemeyi düşündüm:

export const addTodo3 = (text: string) => <AddTodoAction>({
    type: "ADD_TODO",
    text
})

Bu durumda, derleyici artık dönüş türünü şu şekilde algılar, AddTodoActionancak döndürdüğüm nesnenin tüm uygun alanlara sahip olduğunu doğrulamaz.

Bunu farklı bir işlev sözdizimine geçerek çözebilirim:

export const addTodo4 = function(text: string): AddTodoAction {
    return {
        type: "ADD_TODO",
        text
    }
}

export function addTodo5(text: string): AddTodoAction {
    return {
        type: "ADD_TODO",
        text
    }
}

Bu yöntemlerden herhangi biri derleyicinin doğru dönüş türünü kullanmasına ve tüm alanları uygun şekilde ayarladığımı zorlamasına neden olur, ancak bunlar aynı zamanda daha ayrıntılıdır ve thisbir işlevde işlenme şeklini değiştirirler (bu bir sorun olmayabilir, Sanırım.)

Bunu yapmanın en iyi yolu hakkında herhangi bir tavsiye var mı?


6
getTitle = ():string => 'State Lists'
Vikas Bansal

Yanıtlar:


147

İlk olarak, orijinal sorunuzdan aşağıdaki notasyonu düşünün:

export const addTodo3 = (text: string) => <AddTodoAction>({
    type: "ADD_TODO",
    text
})

Bu gösterimi kullanarak, döndürülen nesneyi türe yazarsınız AddTodoAction. Ancak, işlevin bildirilen dönüş türü hala tanımsızdır (ve derleyici dolaylı anyolarak dönüş türü olarak kabul edecektir ).

Bunun yerine aşağıdaki gösterimi kullanın:

export const addTodo3 = (text: string): AddTodoAction => ({
    type: "ADD_TODO",
    text: text
})

Bu durumda, gerekli bir özelliğin çıkarılması beklenen derleyici hatasını verecektir. Örneğin, textmülkün çıkarılması aşağıdaki (istenen) hatayı oluşturacaktır:

Type '{ type: "ADD_TODO"; }' is not assignable to type 'TodoAction'.
  Type '{ type: "ADD_TODO"; }' is not assignable to type 'DeleteTodoAction'.
    Types of property 'type' are incompatible.
      Type '"ADD_TODO"' is not assignable to type '"DELETE_TODO"'.

Ayrıca oyun alanı örneğine bakın .


Bu tam da aradığım notasyon. Maalesef, Visual Studio Code sözdizimi bunu beklentilerime uygun bir şekilde vurgulamıyor, ancak derleyici bunu anlıyor gibi görünüyor.
Brian Hanechak

2

Bence en iyi seçeneğiniz, işleviniz için doğru türlere sahip bir arabirim oluşturmaktır, bu durumda arabiriminizin tüm iç içe türlerini değil, yalnızca bu türü belirtmeniz gerekir:

interface AddTodoAction {
    type: "ADD_TODO",
    text: string
};

interface AddTodoActionCreator {
    (text: string): AddTodoAction;
};

export const addTodo: AddTodoActionCreator = (text) => ({
    type: "ADD_TODO",
    text
});

Güncelleme: Bu türlerle nasıl yapılır

export interface GeneralAction<T> {
    type: string;
    payload: T;
}

export interface GeneralActionCreator<T> {
    (payload: T): GeneralAction<T>;
}

export const SAVE_EVENT = 'SAVE_EVENT';

export const SaveEvent: GeneralActionCreator<UserEvent> = (payload) => { return {type: SAVE_EVENT, payload}; };

2
Bu örnekte jenerikler nasıl kullanılır? AddTodoActionCreator <T>
Jannic Beck

1
UserEventBurada ne var?
1252748
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.