首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型标索引签名和方法

类型标索引签名和方法
EN

Stack Overflow用户
提问于 2019-03-07 23:05:04
回答 2查看 4.5K关注 0票数 8

为什么下面的代码会导致ts(2411)错误?

代码语言:javascript
复制
class Greeter {
    [key: string]: string | number[];
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet(): string {
        return "Hello, " + this.greeting;
    }
}

错误发生在greet(),它说type '() => string'不能分配给type 'string | number[]'

如果我将object添加到索引签名中,错误就会消失。为什么会这样呢?

另外,对于索引签名,它是否使用了any的不良实践?

编辑:我还在签名中添加了接口Function。它也能用。不过,问题是为什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-07 23:23:02

类或具有索引签名的接口中声明的任何属性或方法必须具有与索引中的类型兼容的类型。这就是将Function添加到索引签名中的原因。

原因是在文件中解释

虽然字符串索引签名是描述“字典”模式的一种强大方法,但它们也强制要求所有属性都与其返回类型匹配。这是因为字符串索引声明obj.property也可以作为obj["property"]使用。在下面的示例中,name的类型与字符串索引的类型不匹配,类型检查器提供了一个错误:

代码语言:javascript
复制
interface NumberDictionary {
    [index: string]: number;
    length: number;    // ok, length is a number
    name: string;      // error, the type of 'name' is not a subtype of the indexer
}

any添加到索引器签名可能被认为是一种不好的做法,因为any禁止类型选择,而从any以任何方式获得的任何值也具有any类型,除非另有显式声明,因此使用any会增加出现编译器未报告的类型错误的可能性。

Function添加到该类型更好,因为它正确地描述了类中包含的实际数据--当您使用索引访问获得如下值时

代码语言:javascript
复制
  const key = 'greeting';
  const value = this[key];

如果key恰好等于'greet',您可能会得到一个作为值的函数。此外,当您将字符串值赋值给greet

代码语言:javascript
复制
  this['greet'] = 'hi!';

该方法将被一个字符串值覆盖,您将无法再调用它。

考虑到所有这些,最好将带有索引签名的字典保存在类的单独属性中,而不是在类本身中。像这样的东西可以起作用:

代码语言:javascript
复制
class Greeter {
    data: { [key: string]: string | number[] } = {};

    get greeting(): string { return this.data.greeting.toString() }
    set greeting(value: string) { this.data.greeting = value };

    constructor(message: string) {
        this.greeting = message;
    }
    greet(): string {
        return "Hello, " + this.greeting;
    }
}
票数 6
EN

Stack Overflow用户

发布于 2020-10-17 19:08:49

有一个解决办法可以让你做到这一点。在我的例子中,我希望有一个具有索引签名的类,外加一个自定义设置器和一个返回所有值的属性all (这样我就可以在使用该类时避免丑陋的Object.values )。

这是一个例子。

代码语言:javascript
复制
interface IAccessor<T> {
    [key: string]: T;
}

interface IGetter<T> {
    all: T[]
}

class Accessor<T> {

    get all(): T[] {
        return Object.values<T>(this);
    }

    [key: string]: T | any; // any will do the trick, but it's not enough
}

const accessor: IAccessor<string> & IGetter<string> = new Accessor<string>();
accessor.first = "a";
accessor.second = "b";
accessor.third = "c";
console.log(accessor.all); // ["a", "b", "c"]

剽窃链接

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55054226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档