簡體   English   中英

是否可以在沒有類型斷言或中間體的情況下在 TypeScript 中定義具有屬性的函數?

[英]Is it possible to define a function with properties in TypeScript without a type assertion or intermediate?

TypeScript 允許您定義一個既可調用又具有屬性的接口:

interface FnWithProps {
    (x: number): number;
    a: string;
    b: string;
}

這是創建可分配給此接口的值的一種方法:

function double(x: number) {
    return x * x;
}
double.a = 'Hello';
double.b = 'Goodbye';

let f: FnWithProps = double;  // ok

如果未設置double.adouble.b則會觸發錯誤。

是否可以直接構造這樣的值,而無需通過中間或使用類型斷言?

這不是有效的 TypeScript,會觸發各種錯誤:

let g: FnWithProps = {
    (x: number) => x,
    a: 'Hello',
    b: 'Goodbye',
};

我認為中間解決方案可能是最好的解決方案,因為它也適用於重載,但您也可以使用Object.assign來獲得類似的效果:

let f: FnWithProps = Object.assign(function double(x: number) {
    return x * x;
},{
    a : 'Hello',
    b : 'Goodbye'
}); 

盡管這確實意味着我們無法推斷函數參數或屬性。

如果這是您的常見場景,我們可以構建一個實用函數來對所有內容進行推斷:

interface FnWithProps {
    (x: number): number;
    a: string;
    b: string;
}

function functionWithProps<T extends (...a: any[]) => any>(fn: (...a: Parameters<T>) => ReturnType<T>, props: Pick<T, keyof T>){
    return Object.assign(fn, props);
}

let f = functionWithProps<FnWithProps>(function double(x) { // annotation not necesary
    return x * x;
},{
    a : 'Hello', // helpful intelisense here
    b : 'Goodbye'
}); 

編輯:使用原始帖子中的interface FnWithProps

interface FnWithProps {
    (x: number): number;
    a: number;
    b: number;
}
const g:FnWithProps = (()=>{
    const obj={
        a:2,b:3,
        func:function(x:number){ return this.a*x+this.b}
    }
    return obj.func.bind({a:obj.a,b:obj.b}) as FnWithProps
})()
console.log(g(1))

打字稿游樂場中的演示

這里要注意的是,函數定義的thisobj 這是防止與此相關的錯誤所必需的。 但是,從obj中取出后, this this就丟失了! 所以用bind代替了。 (分配也會起作用)。

順便說一句,使用interface的替代方法如下:

type Fn = (x:number)=>number
type Props = { a: string, b:string}
const g=(function():Fn & Props{
  const f=(x:number)=>x*x
  f.a='Hello'
  f.b='Goodbye'
  return f  // type checking properly applied here
})()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM