2017-06-13 55 views
0

而不必在其他文件中重複委託的形狀,我該如何聲明對具有給定已知類型打印形狀的函數的引用?你如何聲明一個變量擁有一個通用的委託?

功能:

/** 
* @param {object} prev 
* @param {object} next 
* @param {string} name - the name of the child param of both objects to compare 
*/ 
exports.getModification = <T> (prev:T,next:T, name:string):Modification<T> => 
{ 
    const getIsChanging = p => prev[p] != null && p in next && next[p]; 
    const getIsAdding = p => !prev[p] && p in next && next[p]; 
    const getIsDeleting = p => prev[p] != null && p in next && !next[p]; 
    const result:Modification<T> = (
     getIsChanging(name) ? {changeType:'changing',next: next[name]} 
     : getIsAdding(name)? {changeType:'adding', next: next[name]} 
     : getIsDeleting(name) ? {changeType:'deleting',next:undefined} 
     : {changeType:undefined,next:undefined}); 
    return result; 
}; 

我試圖通過

interface Modification<T>{ 
    changeType: string | undefined; 
    next: T | undefined; 
} 
interface GetModificationDelegate<T>{ 
    (prev:T,next:T, name:string) : Modification<T>; 
} 
// try a type alias 
type GetModificationFunction<T> = (prev:T,next:T, name:string) => Modification<T>; 

這些都寫的方法/委託的定義編譯就好了。然而,告訴打字稿符號是對此失敗的一個參考。

var getModification = (app.getModification as GetModificationFunction<T>); 
var getModification: <T>GetModificationFunction<T> = app.getModification; 
var getModification: <T extends{}>GetModificationFunction<T> = app.getModification; 

這些都不編譯。而不訴諸類(我認爲這很簡單)我怎樣才能簡單地告訴打字稿一些東西是它已經知道的一個形狀的一般代表?

回答

1

沒有用參數化類型聲明值的語法,只有泛型函數的一個例外。

但是有一種方法可以繞過這個限制,如果你絕對需要的話。如果您使用ES6 export語句getModification,而不是分配給exports的,你可以用

export type GetModificationFunctionType = typeof getModification; 

因此,例如,完整的源一路上出口其類型「m.ts」模塊是

export interface Modification<T>{ 
    changeType: string | undefined; 
    next: T | undefined; 
} 


export const getModification = <T> (prev:T,next:T, name:string):Modification<T> => 
{ 
    const getIsChanging = p => prev[p] != null && p in next && next[p]; 
    const getIsAdding = p => !prev[p] && p in next && next[p]; 
    const getIsDeleting = p => prev[p] != null && p in next && !next[p]; 
    const result:Modification<T> = (
     getIsChanging(name) ? {changeType:'changing',next: next[name]} 
      : getIsAdding(name)? {changeType:'adding', next: next[name]} 
      : getIsDeleting(name) ? {changeType:'deleting',next:undefined} 
      : {changeType:undefined,next:undefined}); 
    return result; 
}; 

export type GetModificationFunctionType = typeof getModification; 

,你可以在另一個模塊使用它,例如, 「d.ts」:

import {Modification, GetModificationFunctionType} from './m'; 

var g: GetModificationFunctionType; 

g = <T> (prev:T,next:T, name:string):Modification<T> => 
    ({changeType:undefined,next:undefined}); 

更新:如果您只需要在某個類的上下文中使用該委託,則可以將其聲明爲類屬性並具有該類的泛型參數。該物業不能是靜態然而:

class someClass<T> { 
    delegate1: GetModificationDelegate<T>; // ok 

    static delegate2: GetModificationDelegate<T>; //error: Static members 
             // cannot reference class type parameters 
} 

泛型完全從生成的JavaScript代碼刪除,documentation states clearly靜態成員聲明不能引用泛型參數:

正如在以前我們的部分在課堂上,一個課程對其 類型有兩面:靜態面和實例面。通用類只在實例端通用而不是靜態端,因此 在使用類時,靜態成員不能使用類的類型 參數。

+0

我可以在一個類中包裝消費者聲明嗎?將屬性/靜態方法定義爲'GetModificationFunctionType '? – Maslow

+0

是的,你可以在課堂上有聲明,但它不能是靜態的。我更新了答案。 – artem