我有下面的例子,它描述了一個要傳遞給Jumpable類的結構。當我傳遞給測驗類時,我得到了一個錯誤。
type GConstructor<T> = new (...args: any[] ) => T;
type Positionable = GConstructor<{ setPos: (x: number, y: number) => void }> 。
function Jumpable<TBase extends Positionable> (Base: TBase) {
return class Jumpable extends Base{
jump() {
this.setPos(0, 20) 。
}
};
}
class Test {
constructor() {
console.log()。
}
setPos(x: number, y: number) {
console.log()。
}
}
Jumpable<Test>(new Test())。
型別'Test'不滿足'Positionable'的約束。 型別 Test'沒有提供匹配的簽名'new (...args: any[]): { setPos: (x: number, y: number) => void; }'.ts(2344)
。
uj5u.com熱心網友回復:
理解JavaScript 值和TypeScript 型別之間的區別很重要,前者存在于運行時,后者只存在于編譯時。
一個型別有點像一組可能的值。在下面的代碼中:
let x = "hello"。
變數x在運行時將持有值 "hello",而TypeScript編譯器則推斷它具有型別 字串。 而"hello"是構成string型別的可能值之一,所以這很好。 在上面,我們可以說"x的型別是string"。
如果你有一個像x這樣的變數,你可以通過在型別背景關系中使用TypeScript typeof型別查詢運算子來詢問TypeScript的型別(不要與JavaScript typeof運算子混淆):
type TypeofX = typeof x。
// type TypeofX = string
值不是型別,型別也不是值。 很多時候,TypeScript中的值和型別之間存在著清晰明顯的區別,或者說區別很小,可以忽略不計。 例如,與一個值完全對應的 "單子 "或 "單元 "型別通常被賦予與值相同的名稱,例如字串字面型別 "hello"對應于值"hello",因此您可以很好地將一個與另一個混淆。
但是有時一個值和一個型別可以共享一個名字,但是值和型別并不直接對應。發生這種情況的主要情況是class的宣告。
在下面的例子中:
class Foo {
x: string = "hello"
}
我們已經宣告了一個名為Foo的類。在運行時,在JavaScript中,這將創建一個名為Foo的值,這是一個類的建構式。 這個名為Foo的值可以作為一個建構式被呼叫,比如new Foo()。 TypeScript也知道這個值。
此外,class宣告也將一個名為Foo的TypeScirpt 型別帶入范圍,它對應于該類的實體。 一個Foo型別的值應該有一個x型別為string的屬性。
并且Foo值的型別不是Foo型別。 它們是不同的。 Foo值的型別,typeof Foo,有一個construct signature,像new () => Foo。 但是名為Foo的型別卻沒有這樣的構造簽名。
請注意:
const foo。Foo = new Foo() 。
const fooAlias: { x: string } = foo;
const fooCtor: typeof Foo = Foo;
const fooCtorAlias: new () => Foo = fooCtor。
const nope: Foo = Foo; //錯誤!
///Property 'x' is missing in type 'typeof Foo' but required in type 'Foo'
const alsoNope。typeof Foo = new Foo(); // error!
//屬性'prototype'在型別'Foo'中缺失,但在型別'typeof Foo'中是必需的。
foo和fooAlias變數的型別是Foo或同等型別,并且持有Foo類的一個實體。 fooCtor和fooCtorAlias變數的型別是typeof Foo或一個等效的型別,并且持有Foo類的構造器。 如果你試圖將一個變數賦值給另一個,你會得到錯誤。
所以,讓我們看看你的代碼:
type GConstructor<T> = new (...args: any[] )=> T;
type Positionable = GConstructor<{ setPos: (x: number, y: number) => void }> 。
function Jumpable<TBase extends Positionable> (Base: TBase) {
return class Jumpable extends Base{
jump() {
this.setPos(0, 20) 。
}
};
}
這里,Jumpable()函式想要一個TBase型別的Base引數,該引數受制于Positionable,這個型別有一個構造簽名,可以構造{ setPos(x: number, y: number) => void }的實體。 一個Positionable必須是一個類建構式。 這一切都很有意義,因為Jumpable()回傳一個新的類建構式,它是傳入Base的子類。 它看起來像一個mixin類工廠。
Jumpable()希望它的輸入是一個類建構式。
當你呼叫這個時,雖然:
Jumpable< Test>(new Test()。
你已經給它傳遞了一個Test型別的值。 Jumpable()并不想要一個型別為Test的值;那是一個類instance,而不是一個類constructor。 你會得到這樣的錯誤:
Jumpable< Test>(new Test()); //錯誤!
//Type 'Test' does not satisfy the constraint 'Positionable'.
//Type 'Test' 沒有提供匹配的簽名。
// 'new (...args: any[] ): { setPos: (x: number, y: number) => void; }'/span>
這正好告訴你問題所在:你試圖在一個需要建構式型別的地方使用實體型別Test。 Test不是一個建構式;它沒有構造簽名;它是錯誤的。 如果你編譯并運行這段代碼,你也會得到一個運行時錯誤,就像
//
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/318419.html
標籤:
