考慮以下簡單示例:
namespace Calculus {
type Func<T> = {
(arg: T): T;
delta: (arg: T) => T;
};
const f: Func<number> = (x) => x * x; // const cannot be changed to let, why?
f.delta = (x) => 2 * x;
console.log(`f(5) = ${f(5)} and f'(5) = ${f.delta(5)}`);
}
為什么我們不能更改const為let?這是錯誤訊息:
屬性
delta在 type 中缺失(x: number) => number但在 type 中是必需的Func<number>。
uj5u.com熱心網友回復:
對函式的屬性宣告的支持,您可以在其中定義一個函式,然后向其添加屬性,僅在少數特定用例中可用。在實作此功能的拉取請求microsoft/TypeScript#26368 中,“僅適用于用作常量變數初始化程式的函式宣告和函式/箭頭運算式”。
該功能絕對對代碼風格敏感;即使將初始化程式包裝在括號中也會破壞它,如microsoft/TypeScript#46284 所示
因此,您不能更改const為let此處的原因是,這樣做不再初始化 const 變數,因此以正常方式檢查賦值,其中所有屬性都需要在初始化時出現:
const foo: {a: string} = {}; // error!
foo.a = "";
當然,這提出了一個問題:為什么不let支持?雖然在 pull request 中沒有明確說明,但我強烈懷疑這是因為允許可重新分配的變數需要更仔細的檢查以防止無效分配泄漏。例如:
let g: Func<number> = x => x 1; // imagine this is okay
g.delta = x => 1; // then this completes the initialization
g = x => x 7; // but this wrecks it; is this okay?
編譯器需要做一些像控制流分析這樣的事情,g以便在重新分配后“重置”回部分未初始化。這并非不可能實施,但它需要更多的作業,而且可能不值得任何人花費時間或精力。
此外,即使是當前的功能也不做控制流分析,導致有趣的未捕獲的運行時錯誤如下:
const h: Func<number> = x => Math.exp(x); // okay?!
if (1 < 0) { // this never happens
h.delta = h; // the compiler is fooled by this
}
h.delta(1); // no compiler error, but
// RUNTIME ERROR ?? h.delta is not a function
并且允許let或var會使這個問題變得更糟。
Playground 鏈接到代碼
uj5u.com熱心網友回復:
如果你洗掉f.delta = (x) => 2 * x;它也會給你一個錯誤,它可以更改為 let,但const f: Func<number> = (x) => x * x;缺少宣告,delta因此在里面找不到它f,請檢查以下內容:
namespace Calculus {
type Func<T> = {
(arg: T): T;
delta: (arg: T) => T;
};
const createNumberInstance = (): Func<number> => {
const f: Func<number> = x => x * x;
f.delta = x => 2 * x;
return f;
};
const f: Func<number> = (x) => x * x;
f.delta = (x) => 2 * x;
let g: Func<number> = createNumberInstance();
console.log(`g(5) = ${g(5)} and g'(5) = ${g.delta(5)}`);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/368259.html
標籤:打字稿
上一篇:錯誤TS2322:屬性'css'不存在于型別'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>,HTML
