TypeScript:如何从函数返回字段的类型



我想在TypeScript中设计一个函数,该函数访问复杂结构的字段名并返回该字段的类型。例如,有一个Settings类型有几个字段:

export interface Settings {
apiConfig?: ApiConfig;
presentation?: PresentationSettings;
}

我想要一个函数getSettings,可以用作:

let cfg: ApiConfig = getSettings('apiConfig');
let ui: PresentationSettings = getSettings('presentation');

我的第一个方法是使用密钥:

function getSettings(name: keyof Settings): Settings[keyof Settings] {
if (name == 'apiConfig') {
return store.get(name) as ApiConfig;
}
if (name == 'presentation') {
return store.get(name) as PresentationSettings;
}
}

但这意味着返回类型基本上是ApiConfig|PresentationSettings的并集。所以我必须投:

const ui = <PresentationSettings>getSettings('presentation');

不理想。

下一个方法是仿制药:

export function getSettings<T extends Settings[keyof Settings]>(
name: keyof Settings

它可以用作:

const ui = getSettings<PresentationSettings>('presentation');

但在实现功能时:

export function getSettings<T extends Settings[keyof Settings]>(
name: keyof Settings 
{
if (name == 'apiConfig') {
return store.get(name) as ApiConfig;
}
}

我出错了:类型"ApiConfig"不可分配给类型"T"。"ApiConfig"可分配给类型为"T"的约束,但"T"可以用约束的另一个子类型"ApiCnfig|PresentationSettings"实例化。ts(2322(

所以它必须转换为any。也不理想。

还有其他办法吗?

特别是我想称之为不带任何演员阵容:const ui=getSettings("表示"(;并且具有CCD_ 4的实例。这可能吗?

函数肯定需要是泛型的。但是T不应该是返回类型,而应该只是键。返回类型可以使用TSettings进行索引。

function getSettings<T extends keyof Settings>(name: T): Settings[T] {
return {
apiConfig: store.get(name) as ApiConfig,
presentation: store.get(name) as PresentationSettings
}[name]
}

如果您希望实现中没有错误,您将不得不使用某种映射结构,如上面所示。

此实现的问题是,对象中的每个store.get调用都将被急切地执行,如果这是一个昂贵的调用,则这是不理想的。为了避免这种情况,您可以只使用普通的switch语句。但你需要一些断言来掩盖错误。

function getSettings<T extends keyof Settings>(name: T): Settings[T] {
switch (name) {
case "apiConfig": { return store.get(name) as Settings[T] }
case "presentation": { return store.get(name) as Settings[T] }
default: { return undefined as Settings[T] }
}
}

如果您希望完全类型安全,并且不急于执行所有路径,则可以使用包含函数的映射。这里唯一的缺点是额外的函数调用,而且它可能看起来过于冗长。

function getSettings<T extends keyof Settings>(name: T): Settings[T] {

const mapping: {
[K in keyof Settings]: () => Settings[K]
} = {
apiConfig: () => store.get(name) as ApiConfig,
presentation: () => store.get(name) as PresentationSettings
}
return mapping[name]()
}

游乐场

相关内容

  • 没有找到相关文章

最新更新