假設我有一個 TypeScript 類,它有一個名為的屬性birthDate和 3 個基于此屬性的 getter year:month和day.
class User {
birthDate: Date;
get month(): number {
return this.birthDate.getMonth();
}
get year(): number {
return this.birthDate.getFullYear();
}
get day(): number {
return this.birthDate.getDay();
}
}
我可以實體化 a User,設定 abirthDate并正常使用 getter。
const user = new User();
user.birthDate = new Date();
console.log(user.year, user.month, user.day);
但是,顯然,我不能直接設定年份,因為我只有一個 getter(而不是 setter)
// this does not work as expected
user.year = 2022
另一方面,當我嘗試User使用普通物件定義 an 時,TypeScript 編譯器會生成一個錯誤,指出我缺少屬性(year和month)day:
// this does not works... why?
const user: User = {
birthDate: new Date()
}
我的問題是:為什么我應該在普通物件中定義這些屬性,因為它們只是吸氣劑?在這種情況下,如何User使用普通物件創建 s ?
作業代碼在這里
uj5u.com熱心網友回復:
這里的關鍵詞是new。在您的第一個示例中,您實際上是在實體化User. 在您的第二個示例中,您只是創建了一個看起來像用戶的物件(即具有用戶的所有屬性)。
您可以通過提供所有屬性/getters/etc 來創建一個看起來像用戶的物件。但是,重要的是要了解其后果是什么。請注意建構式的不同之處。
class User {
birthDate: Date;
get month(): number {
return this.birthDate.getMonth();
}
get year(): number {
return this.birthDate.getFullYear();
}
get day(): number {
return this.birthDate.getDay();
}
}
const user1 = new User();
user1.birthDate = new Date(2010, 10, 22);
console.log("Constructor Name:" user1.constructor.name); //prints "Constructor Name: User":
const user2: User = {
birthDate: new Date(2010, 10, 22),
get month(): number {
return this.birthDate.getMonth();
},
get year(): number {
return this.birthDate.getFullYear();
},
get day(): number {
return this.birthDate.getDay();
},
}
console.log("Constructor Name:" user2.constructor.name); //prints "Constructor Name: Object"
打字稿操場演示
uj5u.com熱心網友回復:
當你寫
const user: User = {
birthDate: new Date()
}
您不創建User物件。您只需創建一個具有屬性的物件birthDate。此物件不滿足宣告所隱含的介面,因為User它沒有屬性month和。yearday
你知道 Javascript 沒有真正的類嗎?它只有物件。在純舊的 Javascript 中,不是class宣告,有人寫道
function User(birthDate) {
this.birthDate = birthDate;
}
User.prototype.getYear = function () {
return this.birthDate.getYear();
}
User.prototype.getMonth = function () {
return this.birthDate.getMonth();
}
User.prototype.getDay = function () {
return this.birthDate.getDay();
}
var user = new User(new Date());
一個函式,在這里User()可以作為一個建構式,當用new一個物件呼叫它時,它是使用類的prototype物件作為原型創建的(實際上,它是通過物件的__proto__屬性鏈接起來的)。
class宣告只是舊模式的語法糖。
uj5u.com熱心網友回復:
我的問題是:為什么我應該在普通物件中定義這些屬性,因為它們只是吸氣劑?
因為您的型別說只讀year,month和day屬性將存在于User物件上,但您嘗試分配給型別變數的物件上沒有任何屬性User。
在這種情況下,如何使用普通物件創建用戶?
通過提供吸氣劑:
const user: User = {
birthDate: new Date(),
get month(): number {
return user.birthDate.getMonth();
},
get year(): number {
return user.birthDate.getFullYear();
},
get day(): number {
return user.birthDate.getDay();
},
};
游樂場鏈接
但是使用建構式似乎是合理的,因此您可以在原型上重用 getter。
為了完整性:您也可以通過讓原始物件從帶有這些 getter 的原型繼承來做到這一點;這可能最好封裝為一個函式:
interface User {
birthDate: Date;
readonly month: number;
readonly year: number;
readonly day: number;
}
const UserGetters: Partial<User> = {
get month(): number {
return this.birthDate!.getMonth();
},
get year(): number {
return this.birthDate!.getFullYear();
},
get day(): number {
return this.birthDate!.getDay();
}
};
function makeUser(init: Pick<User, "birthDate">): User {
return Object.assign(Object.create(UserGetters), init);
}
const user = makeUser({birthDate: new Date()})
console.log(user.year); // 2022 (at the moment)
游樂場鏈接
(我用非空斷言稍微作弊,因為我知道該makeUser函式不允許birthDate未指定或null.)
Some folks don't like constructor functions but do like prototypes, so that's an option for them.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/426127.html
標籤:javascript 打字稿
下一篇:如何根據下拉選擇顯示或隱藏資料
