是否有方法来描述转换对象的功能?



我有一个这样的函数

function transform(obj) {
const returnedObj = { custom: {} };
for (key in obj.wrap.custom) {
returnedObj.custom[key] = obj.wrap.custom[key];
}
return returnedObj;
}

描述类型的正确方法是什么?我已经试过了

interface ITransformingObject {
wrap: {
custom: {[key: string]: string}
}
}
interface IReturnedObject {
custom: ITransformingObject['wrap']['custom']
}
function transform(obj: ITransformingObject): IReturnedObject {
const returnedObj = { custom: {} };
for (const key in obj.wrap.custom) {
returnedObj.custom[key] = obj.wrap.custom[key];
}
return returnedObj;
}
const a = { 
wrap: { 
custom: {
test: 'test'
}
}
}
const b = transform(a);

但我不确定它是否正确。例如,智能感知看不到a.custom的属性。我可以更好地描述返回类型来定义a.custom的键必须与a.wrap.custom的键相同吗?

为了跟踪custom属性中的特定对象类型,需要使用泛型,如下所示:

interface ITransformingObject<T extends object> {
wrap: {
custom: T
}
}
interface IReturnedObject<T extends object> {
custom: T
}
function transform<T extends object>(obj: ITransformingObject<T>): IReturnedObject<T> {
const returnedObj = { custom: {} } as IReturnedObject<T>;
for (const key in obj.wrap.custom) {
returnedObj.custom[key] = obj.wrap.custom[key];
}
return returnedObj;
}

这里ITransformingObject<T>有一个wrap属性和一个custom属性,类型为T,对于一些类似于你指定的T对象。IReturnedObject<T>是相同的,但没有wrap包装器。那么transform()也是泛型的;对于某些T,它的参数类型为ITransformingObject<T>,然后对于相同的T返回IReturnedObject<T>类型的值。

还需要注意的是,为了使编译没有错误,我需要断言returnedObjectIReturnedObject<T>类型,因为它最初不是为真(当然在初始化时,{}的值不太可能是T类型)。

现在,当您调用transform()时,编译器将根据您传入的值的类型为您推断类型参数T:

const a = {
wrap: {
custom: {
test: 'test'
}
}
}
const b = transform(a);
/* function transform<{
test: string;
}>(obj: ITransformingObject<{
test: string;
}>): IReturnedObject<{
test: string;
}> */

T是如何被推断为{test: string}的,因此b的类型是IReturnedObject<{test: string}>。这意味着编译器现在知道b.custom中应该存在或不应该存在哪些属性:

console.log(b.custom.test.toUpperCase()); // compiles fine, "TEST"
b.custom.nope // compiler error, nope does not exist on {test: string}

Playground链接到代码

最新更新