【发布时间】:2021-08-23 02:35:22
【问题描述】:
假设我写了这样的代码
type ResourceDecorator = (input: UserResourceDefinition) => DecoratedResourceDefinition
const decorate: ResourceDecorator = ...
const resources = decorate({
Book1: {
resourceName: 'my-book',
resourceType: 'book'
},
Pencil1: {
resourceName: 'my-pencil',
resourceType: 'pencil'
}
})
我想编写函数decorate(...),这样输入类型(Book1,Pencil1)中的所有第一级键都保留在输出类型中。换句话说,我想像这样使用输出resources
// somewhere else
console.log(resources.Book1.resourceName)
// the decorate() function will add some programmatically
// defined properties in addition to the user definition.
console.log(resources.Book1.exampleDecorationProperty)
我已经尝试过像这样的可索引对象语法,但它不起作用。
export interface UserResourceDefinition {
[key: string]: {
resourceName: string,
resourceType: string,
}
}
export interface DecoratedResourceDefinition {
[key: string]: {
resourceName: string,
resourceType: string,
exampleDecorationProperty: string
}
}
type ResourceDecorator = (input: UserResourceDefinition) => DecoratedResourceDefinition
const decorate: ResourceDecorator = (input) => {
return Object.entries(definition).map(([resourceKey, userDef]) => ({
resourceName: userDef.resourceName,
resourceType: userDef.resourceType,
resourceKey: resourceKey,
exampleDecorationProperty: someFunction(userDef)
})).reduce((accumObj, decoratedDef) => ({ ...accumObj, [decoratedDef.resourceKey]: decoratedDef }), {});
}
它不起作用,因为输出的类型resources 不知道它具有属性Book1 和Pencil1。
// somewhere else
// The auto completion cannot infer 'resources.Book1'
console.log(resources.Book1.resourceName)
// The compiler does not complain about non-existing property 'Foo'
console.log(resources.Foo.resourceName)
Typescript 可以做到这一点吗?
【问题讨论】:
-
你可以使用泛型定义你想要的类型` T & {[key in keyof T]: {exampleDecorationProperty:string}}
, but I'm not sure there is an elegant way of convincing TS that the result of your function conforms to that type. Idk if you're okay withreturn res as T & {[key in keyof T]: {exampleDecorationProperty:string}}` -
@NadiaCibrikova 您的解决方案很有希望,但一个新问题是我不知道如何在函数中编写实现以满足类型定义。似乎
Object.entries().reduce()删除了有关输入类型的所有信息。你有什么想法让我试试看。谢谢。 -
那就是问题所在,我觉得TS没有办法判断修饰后的类型是否正确。因此,如果您确信自己做对了,您可以返回结果,说明它是您需要的类型(使用
as关键字)。这意味着装饰器函数之外的代码将受到类型检查的保护,但函数本身将易受攻击。
标签: javascript typescript ecmascript-6 types