【问题标题】:Typescript Interface Optional Method Property UndefinedTypescript 接口可选方法属性未定义
【发布时间】:2017-11-11 15:48:02
【问题描述】:

我正在深入学习有关 Typescript 的 Pluralsites 课程。使用接口时,我有以下几点:

interface Book {
    id: number;
    title: string;
    author: string;
    available: boolean;
    category: Category;
    pages: number;
    markDamaged: DamageLogger;
}

interface DamageLogger {
    (reason: string): void;
}

我现在宣布一本书如下:

let myBook: Book = {
    id: 5,
    title: 'Pride and Prejudice',
    author: 'Jane Austen',
    available: true,
    category: Category.Fiction,
    pages: 250,
    markDamaged: (reason: string) => console.log('Damaged: ' + reason)
};

myBook.markDamaged('missing back cover');

一切都很好,但只要我将 markDamaged 的​​界面更改为可选,如下所示:

interface Book {
    id: number;
    title: string;
    author: string;
    available: boolean;
    category: Category;
    pages: number;
    markDamaged?: DamageLogger;
}

编译器在这一行咆哮:

myBook.markDamaged('missing back cover');

并说 markDamaged 属性可能未定义。我把问号去掉,一切又好了。

有什么想法吗?我在课程的其他地方使用可选参数没有问题,但是在使用接口时,这就是我所看到的。

感谢您的帮助。

【问题讨论】:

  • 好吧,既然 markDamaged 被标记为可选,它不可能存在于对象中。如果它不存在,则它是未定义的。所以你需要在调用它之前检查它是否存在。

标签: typescript interface


【解决方案1】:

如果您声明markDamaged?: DamageLogger,您的意思是Book 可能有也可能没有markDamaged 属性。然后,编译器会强制您检查Book(包括myBook)实际上是否有markDamaged,然后才会让您调用它。仅当设置了 --strictNullChecks 编译器选项时才启用此检查。

这行得通

interface Book {
    markDamaged: DamageLogger
}
interface DamageLogger {
    (reason: string): void
}

let myBook: Book = {
    markDamaged: (reason: string) => console.log('Damaged: ' + reason)
}
// myBook: Book; it definitely has markDamaged
myBook.markDamaged('missing back cover')

这不是

interface Book { markDamaged?: DamageLogger }
// ...
// myBook: Book; Books do not definitely have markDamaged
myBook.markDamaged('...')

但这确实

if(myBook.markDamaged) {
    // Now we know it's there, we can call it
    myBook.markDamaged('...')
}

这也有效:

interface Book { markDamaged?: DamageLogger }
// don't say it's a Book
// inferred: myBook: { markDamaged: (reason: String) => void }
// TypeScript's type system is structural, not nominal
// The identity of a type is in it's structure, not name
// myBook's type says that it definitely has markDamaged
let myBook = { markDamaged: (reason: String) => console.log('Damaged: ' + reason) }
myBook.markDamaged('...')

function read(b: Book) {}
// myBook's type is a subtype of Book, because a Book can be missing markDamaged but myBook definitely has it.
read(myBook)

【讨论】:

  • 伙计,这个真的很奇怪。如果将界面中的 pages 属性设为可选,我可以将其称为 no prob,例如:myBook.pages = 10。因为 'markDamaged' 是一种方法,所以它不喜欢它。
  • 您正在设置属性;所以如果它丢失了,它会被创建。是否是可选的并不重要。
【解决方案2】:

那是因为它不能保证被定义。首先检查它,编译器应该停止抱怨。

if (myBook && myBook.markDamaged) {
    myBook.markDamaged('missing back cover');
}

【讨论】:

    猜你喜欢
    • 2021-08-27
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 2012-12-06
    • 2022-01-22
    相关资源
    最近更新 更多