ค่าดีฟอลต์ของอินเตอร์เฟซใน Typescript
ฉันมีอินเตอร์เฟซดังต่อไปนี้ใน TypeScript:
interface IX {
a: string,
b: any,
c: AnotherType
}
ฉันประกาศตัวแปรของประเภทนั้นและฉันกำหนดค่าเริ่มต้นให้กับคุณสมบัติทั้งหมด
let x: IX = {
a: 'abc',
b: null,
c: null
}
แล้วฉันกำหนดค่าจริงให้กับมันในฟังก์ชัน init ภายหลัง
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
แต่ผมไม่ชอบที่จะต้องระบุค่ามาตรฐานเป็น null สำหรับแต่ละคุณสมบัติเมื่อประกาศอ็อบเจ็กต์ทั้งๆ ที่ค่าพวกนั้นจะถูกตั้งเป็นค่าจริงในภายหลัง ผมสามารถบอกอินเทอร์เฟซให้ตั้งค่าคุณสมบัติที่ผมไม่ได้ระบุเป็น null โดยอัตโนมัติได้ไหม? อะไรที่จะทำให้ผมทำแบบนี้ได้:
let x: IX = {
a: 'abc'
}
โดยไม่เกิดข้อผิดพลาดของคอมไพเลอร์ ตอนนี้มันบอกฉันว่า
TS2322: ประเภท '{}' ไม่สามารถกำหนดค่าให้กับประเภท 'IX' ได้ คุณสมบัติ 'b' ไม่มีในประเภท '{}'
คำตอบ #1
ฉันสามารถบอกอินเทอร์เฟซให้ตั้งค่าคุณสมบัติที่ฉันไม่ได้ระบุเป็น null ได้ไหม? อะไรที่จะทำให้ฉันทำสิ่งนี้ได้
ไม่ คุณไม่สามารถให้ ค่าเริ่มต้น สำหรับอินเทอร์เฟซหรืออาลิแอสของชนิดได้เนื่องจากมันมีผลเฉพาะเวลาคอมไพล์ และค่าดีฟอลต์จำเป็นต้องมีการสนับสนุนเวลารันไทม์
ทางเลือก
แต่ค่าที่ไม่ได้ระบุจะถูกตั้งค่าเริ่มต้นเป็น undefined ในรันไทม์ของ JavaScript ดังนั้นคุณสามารถทำเครื่องหมายว่าเป็นค่าที่ไม่จำเป็นได้:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
และตอนนี้เมื่อคุณสร้างมัน คุณเพียงแค่ต้องระบุ a:
let x: IX = {
a: 'abc'
};
คุณสามารถให้ค่าตามที่ต้องการได้:
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
คำตอบ #2
คุณไม่สามารถกำหนดค่าดีฟอลต์ในอินเทอร์เฟซได้ แต่คุณสามารถทำสิ่งที่คุณต้องการได้โดยการใช้คุณสมบัติที่เป็นอ็อปชัน:
เพียงแค่เปลี่ยนอินเทอร์เฟซเป็น:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
คุณสามารถทำได้ดังนี้:
let x: IX = {
a: 'abc'
}
และใช้ฟังก์ชัน init ของคุณเพื่อกำหนดค่าดีฟอลต์ให้กับ x.b และ x.c หากคุณสมบัติเหล่านั้นยังไม่ได้ถูกตั้งค่า
คำตอบ #3
ในขณะที่คำตอบของ @Timar ใช้งานได้อย่างสมบูรณ์สำหรับค่าเริ่มต้น null (ซึ่งเป็นสิ่งที่ถูกถามมา) นี่คืออีกหนึ่งวิธีง่าย ๆ ที่อนุญาตให้ใช้ค่าเริ่มต้นอื่น ๆ ได้: กำหนดอินเทอร์เฟซตัวเลือกรวมถึงค่าคงที่ที่เกี่ยวข้องซึ่งมีค่าเริ่มต้น; ในตัวสร้าง ใช้ตัวดำเนินการกระจายเพื่อกำหนดตัวแปรสมาชิก options
interface IXOptions {
a?: string,
b?: any,
c?: number
}
const XDefaults: IXOptions = {
a: "default",
b: null,
c: 1
}
export class ClassX {
private options: IXOptions;
constructor(XOptions: IXOptions) {
this.options = { ...XDefaults, ...XOptions };
}
public printOptions(): void {
console.log(this.options.a);
console.log(this.options.b);
console.log(this.options.c);
}
}
ตอนนี้คุณสามารถใช้คลาสได้แบบนี้:
const x = new ClassX({ a: "set" });
x.printOptions();
ผลลัพธ์ :
set
null
1
คำตอบ #4
คุณสามารถนำอินเทอร์เฟซไปใช้กับคลาสได้ จากนั้นคุณสามารถจัดการกับการเริ่มต้นสมาชิกในคอนสตรัคเตอร์ได้:
class IXClass implements IX {
a: string;
b: any;
c: AnotherType;
constructor(obj: IX);
constructor(a: string, b: any, c: AnotherType);
constructor() {
if (arguments.length == 1) {
this.a = arguments[0].a;
this.b = arguments[0].b;
this.c = arguments[0].c;
} else {
this.a = arguments[0];
this.b = arguments[1];
this.c = arguments[2];
}
}
}
วิธีอีกอย่างคือการใช้ฟังก์ชันโรงงาน:
function ixFactory(a: string, b: any, c: AnotherType): IX {
return {
a: a,
b: b,
c: c
}
}
จากนั้นคุณสามารถทำได้ง่ายๆ:
var ix: IX = null;
...
ix = new IXClass(...);
// or
ix = ixFactory(...);
คำตอบ #5
คุณสามารถใช้ประเภทแมป Partial ตามที่อธิบายในเอกสาร: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
ในตัวอย่างของคุณ คุณจะมี:
interface IX {
a: string;
b: any;
c: AnotherType;
}
let x: Partial<IX> = {
a: 'abc'
}
คำตอบ #6
ฉันใช้รูปแบบดังต่อไปนี้:
สร้างประเภทยูทิลิตี้ Defaults<T>:
type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
type Defaults<T> = Required<Pick<T, OptionalKeys<T>>>
ประกาศคลาสพร้อมตัวเลือก/ค่าเริ่มต้น:
// options passed to class constructor
export interface Options {
a: string,
b?: any,
c?: number
}
// defaults
const defaults: Defaults<Options> = {
b: null,
c: 1
};
export class MyClass {
// all options in class must have values
options: Required<Options>;
constructor(options: Options) {
// merge passed options and defaults
this.options = Object.assign({}, defaults, options);
}
}
สร้างอินสแตนซ์ของคลาส:
const myClass = new MyClass({
a: 'hello',
b: true,
});
console.log(myClass.options);
// { a: 'hello', b: true, c: 1 }
