【发布时间】:2015-04-13 08:02:22
【问题描述】:
问题/答案 - 2021 年更新
这个问题是 6 年前提出的,当时我对 Typescript 了解甚少! 我不想删除它,因为还有一些人在看这篇文章。
如果你想让一个变量的类型成为另一个变量的属性,你可以使用keyof。
例子:
interface User {
name: string;
age: number;
}
const nameProperty: keyof User = 'name'; // ok
const ageProperty: keyof User = 'age'; // ok
const emailProperty: keyof User = 'email'; // not ok
如果您想要一个方法接受一个参数,该参数是另一个参数的属性,您可以使用泛型将这两种类型链接在一起。
使用泛型的示例 + keyof:
const foo = <TObject extends object>(
object: TObject,
property: keyof TObject
) => {
// You can use object[property] here
};
foo({ a: 1, b: 2 }, 'a'); // ok
foo({ a: 1, b: 2 }, 'b'); // ok
foo({ a: 1, b: 2 }, 'c'); // not ok
使用泛型的示例 + Record:
const foo = <TKey extends string>(
object: Record<TKey, unknown>,
property: TKey
) => {
// You can use object[property] here
};
foo({ a: 1, b: 2 }, 'a'); // ok
foo({ a: 1, b: 2 }, 'b'); // ok
foo({ a: 1, b: 2 }, 'c'); // not ok
请不要使用这个问题的答案! 如果你在某个时候重命名属性,Typescript 会自动告诉你有错误。
原始问题(2014 年)
目标
我有一个 TypeScript 接口:
interface IInterface{
id: number;
name: string;
}
我有一些方法可以输入属性的名称(字符串)。
前:
var methodX = ( property: string, object: any ) => {
// use object[property]
};
我的问题是当我调用methodX时,我必须将属性名写成字符串。
例如: methodX("name", objectX); objectX 实现 IInterface 的地方
但这是不好:如果我重命名一个属性(假设我想将name 重命名为lastname),我将不得不手动更新我的所有代码。
而且我不想要这种依赖。
由于 typescript 接口没有 JS 实现,我看不出我怎么不能使用字符串。
我想要类似的东西:methodX(IInterface.name.propertytoString(), objectX);
我对 JS 还很陌生,你有什么替代方法吗?
(可选)更多细节:为什么我需要将属性作为参数传递,为什么我不使用泛型方法?
我使用链接数据的方法:
linkData = <TA, TB>(
inputList: TA[],
inputId: string,
inputPlace: string,
outputList: TB[],
outputId: string ) => {
var mapDestinationItemId: any = {};
var i: number;
for ( i = 0; i < outputList.length; ++i ) {
mapDestinationItemId[outputList[i][outputId]] = outputList[i];
}
var itemDestination, itemSource;
for ( i = 0; i < inputList.length; ++i ) {
itemDestination = inputList[i];
itemSource = mapDestinationItemId[itemDestination[inputId]];
if ( itemSource ) {
itemDestination[inputPlace] = itemSource;
}
}
};
但是 TA 和 TB 可以有很多不同的 id。所以我不知道如何使它更通用。
【问题讨论】:
标签: javascript typescript