有没有办法让智能感知知道具有动态索引的接口的实例成员?

时间:2019-04-05 05:25:28

标签: angular typescript visual-studio-code

我正在做一个有角度的项目,并且正在使用一个界面来定义模块的配置。该界面旨在将名称映射到对象,并且非常简单:

export interface NamedRoutes {
  [routeName: string]: NamedRoute;
}

当我创建该接口的实例时,使用它时intellisense无法解析该实例的成员。例如:

const routes: NamedRoutes {
  someRoute: {...}
};

const someRoute = routes. // no intellisense support here

据我所知,问题是,当编译器尝试回溯成员时,它会看到索引是字符串,因此可以允许任何内容,因此它无法建议实际存在的成员。

当我省略常数的键入时,intellisense能够建议正确的成员。据我所知,这是因为索引名随后被解释为符号,而不是字符串。缺点是,当我的API用户将对象传递给我的配置方法时,他们只会得到错误的编译器支持,在我们的项目中,该错误可能与对象创建完全不同。我认为,对于该API而言,这将是非常糟糕的用户体验。

我尝试使用Record<string, NamedRoute><T extends string = string>等不同的高级类型(用于索引类型)。

我希望我已经明确了我的问题是什么以及我要实现的目标。有合适的方法吗?

P.S .:对于我们的项目,也可以选择使用类型而不是接口。

1 个答案:

答案 0 :(得分:1)

您可以为用户提供帮助功能,使他们可以使用它们来创建NamedRoutes实例,而不是让他们使用NamedRoutes注释。像这样:

// I like examples that compile, so here's something random:
interface NamedRoute {
    whoKnows: string; 
}

export interface NamedRoutes {
    [routeName: string]: NamedRoute;
}

// helper function that just returns the input but makes sure it conforms to NamedRoutes    
const asNamedRoutes = <T extends NamedRoutes>(t: T) => t;

// correct use
const routes = asNamedRoutes({
    someRoute: { whoKnows: "blah" }
});

routes.someRoute // IntelliSense is here, yay!

// incorrect use so you still get early errors
const badRoutes = asNamedRoutes({
    badRoute: { nobodyKnows: "whoops " } // error!
    // type { nobodyKnows: string } is not assignable to NamedRoute
})

asNamedRoutes()函数本质上与强迫人们比通常将对象传递给方法的方法相同,因此可以更早地发现错误。您可以采取一些措施来减少对NamedRoutes的注释的可能性(使NamedRoutes成为具有私有成员的类会产生这种效果),但这可能是过大了。

希望有帮助。祝你好运!