我想拥有一个函数,该函数带有一个带有可选键(inst
)的对象,然后该对象将使用inst
对象的键来创建返回对象-例如:< / p>
function init( db, config ) {
let ret = {};
if ( config.inst ) {
for (let [key, value] of Object.entries(config.inst)) {
ret[ key ] = value+1; // would normally do some kind of processing here
}
}
return ret;
}
如果使用init( db, { inst: { a: 1, b: 2 } } );
进行了调用,它将返回{ a: 2, b: 3 }
。是的,它有点多余,但是它可以简化我的想法!
虽然很容易用Java编写代码,但我终生无法找到我应该为此函数定义的接口,以让TypeScript处理返回的数据和类型。
让我烦恼的关键是如何获取inst
嵌套对象的密钥。我知道我可以使用keyof
或in
来获取对象的键,但是在这里看不到如何应用它。
确实非常欢迎任何帮助!
跟进-更改返回属性的类型
作为后续操作,此答案假定返回的参数类型将与为inst
传递的参数匹配。如果更改类型怎么办?例如将数字更改为字符串,反之亦然?
type Config<T extends {}> = {
inst?: T
}
function init<T extends {}>(db, config: Config<T>): T & {} {
let ret: any = {};
if ( config.inst ) {
for (let [key, value] of Object.entries(config.inst)) {
if ( typeof value === 'number' ) {
ret[ key ] = value.toString();
}
else {
ret[ key ] = parseInt( value, 10 );
}
}
}
return ret;
}
let { num, str } = init( null, { inst: { num: '1', str: 2 } } );
这样,被破坏的num
将是一个字符串,而str
将是一个数字,对于该函数执行的“处理”而言,这是不正确的。有没有办法让TypeScript推断正确的类型?
答案 0 :(得分:1)
如果我对您的理解正确,则类似的内容应该可以代表您的工作,因此您实际上不需要执行任何操作即可正确传播类型信息:
type Config<T extends {}> = {
inst?: T
}
function init<T extends {}>(db, config: Config<T>): T | {} {
let ret = {};
if ( config.inst ) {
for (let [key, value] of Object.entries(config.inst)) {
ret[ key ] = value+1; // would normally do some kind of processing here
}
}
return ret;
}
对于错误的情况,您可能应该返回空对象(例如,未定义)以外的其他内容,以便以后以TypeScript理解的方式更容易地检查发生了哪种情况。
答案 1 :(得分:1)
如果您需要更改成员的类型,则需要在返回类型中添加一些映射类型和条件类型(有关它们的文档,请参见here)。您将需要根据条件类型来表达您执行的处理(实际上是根据类型来重复处理算法),但至少调用者会获得适当的类型:
type Config<T extends {}> = {
inst?: T
}
function init<T extends {}>(db, config: Config<T>): {
[P in keyof T]: // take each property of T
T[P] extends number ? string : number // If the property T[P] is a number the new property type will be string otherwise it will be number
} {
let ret: any = {};
if ( config.inst ) {
for (let [key, value] of Object.entries(config.inst)) {
if ( typeof value === 'number' ) {
ret[ key ] = value.toString();
}
else {
ret[ key ] = parseInt( value, 10 );
}
}
}
return ret;
}
let { num, str } = init( null, { inst: { num: '1', str: 2 } } );