如何访问用Typescript中的接口声明的属性的属性?

如何访问用Typescript中的接口声明的属性的属性?,typescript,Typescript,我正在尝试以下代码: export interface IEnumElement { elem: string; text: string; val: number } export interface IIndexable<T> { [index: string]: T; } export class AdminBase { ExamStatusId: IIndexable<IEnumElement> = {

我正在尝试以下代码:

export interface IEnumElement {
    elem: string;
    text: string;
    val: number
}
export interface IIndexable<T> {
    [index: string]: T;
}  
export class AdminBase {

    ExamStatusId: IIndexable<IEnumElement> = {
        All: {
            elem: "",
            text: 'Exam Status: All',
            val: 0
        },
        Current: {
            elem: "asdf",
            text: 'Exam Status: Current',
            val: 1
        }
    }
}

var x = new AdminBase();
var y = x.ExamStatusId.All;
导出接口IEnumElement{
元素:字符串;
文本:字符串;
瓦尔:号码
}
导出接口IIindexable{
[索引:字符串]:T;
}  
导出类AdminBase{
ExamStatusId:IIndexable={
全部:{
元素:“,
文本:“考试状态:全部”,
瓦尔:0
},
当前:{
元素:“asdf”,
文本:“考试状态:当前”,
瓦尔:1
}
}
}
var x=新的AdminBase();
变量y=x.ExamStatusId.All;
这给了我一个错误,说:

Error   1   The property 'All' does not exist on value of type 
'IIndexable<IEnumElement>'. C:\Protractor\TypeScript1.ts
错误1类型的值上不存在属性“All”
“IIndexable”。C:\dragrator\TypeScript1.ts

请注意,ExamStatusId现在只有两个属性,但以后可能会有任意数量的不同属性。

这里的要点是,我们声明
ExamStatusId的类型将实现此接口
IIndexable

因此,这里访问该成员的唯一方法是通过字符串索引器:

var y = x.ExamStatusId["All"];

请查看我对您上一个问题的回答。。。您将看到,我的解决方案实际上允许访问
All
属性

我将再次强调TypeScript中依靠类型推断的美妙之处。您不需要显式地注释程序中的所有内容,您可以让编译器和语言服务来完成这项艰巨的工作

代码的“类型推断版本”为您提供:

  • 消费点IEnumElement的类型安全性
  • 如果将
    ExamStatusId
    属性用作IEnumElement,请键入其安全性
  • 访问
    All
    属性
  • 少手写注释
以下是完整的示例:

interface IEnumElement {
    elem: string;
    text: string;
    val: number
}

class Exam {
    private examStatusSelectId: number;

    ExamStatusId = {
        All: {
            id: this.examStatusSelectId,
            elem: '',
            text: 'Exam Status: All',
            val: 0
        },
        Current: {
            id: this.examStatusSelectId,
            elem: '',
            text: 'Exam Status: Current',
            val: 1
        }
    }
}

// This function must be passed an IEnumElement
function example(element: IEnumElement) {

}

var exam = new Exam();

// The compiler knows this is good
example(exam.ExamStatusId.All);

如果我要更改[index:string]的话,有没有办法改变这一点。必须在字符串中指定“All”是我试图避免的一个问题,因为如果我错误地输入“All”,我会看到问题。你认为我应该回到这个解决方案吗:我明白100%! 当我开始使用这个符号时,我想:“嘿,如果我输入
ExamStatusId[“All”]
而不是
ExamStatusId.All
,我就失去了类型安全性了。”但是你知道吗?用纯JS
ExamStatusId表示的符号。所有的
也不保存。。。在JAVA或C语言的词典中。。。字典不是类型安全的。。如果你要一把钥匙。。。事后检查。。在单元测试中。。。我知道很糟糕;(…但是…最后一点注意:我们总是可以做
(ExamStatusId).all
…但是小的
a
而不是
all
将在以后导致错误…您可以使用
ExamStatusId访问它。all
具有完整的类型安全性。请参阅我的答案。我们在这里看到的是,您正在使用类型
检查
。这是一种按原样定义的类型…但这不是OP情况-即使可以解决(我不知道这个问题;)。我试图解释TypeScript字典是如何工作的——例如,使用类似于
IIndexable
的类型。因此,当您的示例运行时,它正在更改实现(这可能仍然是正确的);)TypeScript允许我们将大量现有的基于类的知识引入JavaScript。在可能的情况下,我们应该抛弃我们对名义类型系统的知识,接受结构类型系统。如果我们使用TypeScript是因为它提供了静态类型检查,那么任何需要魔法字符串的解决方案都不如静态类型的解决方案。同样,实现也没有什么不同,它只是由编译器而不是程序员来表达。
var y = x.ExamStatusId["All"];
interface IEnumElement {
    elem: string;
    text: string;
    val: number
}

class Exam {
    private examStatusSelectId: number;

    ExamStatusId = {
        All: {
            id: this.examStatusSelectId,
            elem: '',
            text: 'Exam Status: All',
            val: 0
        },
        Current: {
            id: this.examStatusSelectId,
            elem: '',
            text: 'Exam Status: Current',
            val: 1
        }
    }
}

// This function must be passed an IEnumElement
function example(element: IEnumElement) {

}

var exam = new Exam();

// The compiler knows this is good
example(exam.ExamStatusId.All);