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

问题描述 投票:1回答:1

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

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。:使用类型而不是接口也是我们项目的选项。

angular typescript visual-studio-code
1个回答
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成为一个有私人成员的类会产生这种效果),但那可能有点过分。

希望有所帮助。祝好运!

© www.soinside.com 2019 - 2024. All rights reserved.