[英]Using the keys of an object literal as a Typescript type?
I have an object which contains some predefined data for my application, which is stored in a const variable like this:我有一个对象,其中包含我的应用程序的一些预定义数据,它存储在一个常量变量中,如下所示:
const data:{[key:string]:any} =Object.freeze({
some: 123,
long: {"a":"b"},
list: ["c"],
of: "",
arbitrary: null,
things: 1.2,
});
The keys of this object are known to the rest of the application.该对象的键对于应用程序的其余部分是已知的。 Consider this function which accesses the data object:
考虑这个访问数据对象的函数:
function doWork(k) {
if(!data.hasOwnProperty(k)) throw Error();
let value = data[k];
//...
}
This is called with strings like这被称为字符串
doWork("things");
I would like to replace that runtime error for invalid keys with a Typescript compile-time check.我想用 Typescript 编译时检查替换无效键的运行时错误。 I would like to be able to write
我希望能够写
function doWork(k: keyof data) {
let value = data[k];
//...
}
But apparently the keyof
operator does not work that way.但显然
keyof
运算符不能那样工作。 I get an error TS2304: Cannot find name 'data'.
我收到错误
TS2304: Cannot find name 'data'.
My workaround: I can extract the keys of the object with something like this:我的解决方法:我可以用这样的东西提取对象的键:
console.log("\""+Object.keys(data).join("\"|\"")+"\"");
Which I can then copy/paste and define as a type.然后我可以复制/粘贴并定义为类型。
type data_key = "some"|"long"|"list"|"of"|"arbitrary"|"things"
export function doWork(k:data_key) {
let value = data[k];
//...
}
This feels like a silly hack and is quite inconvenient whenever I have to make a change, because I have to remember to put in this statement at the right place, run the program, and manually copy in the values back into the source code (or realistically, just type in the changes myself).这感觉就像一个愚蠢的 hack 并且每当我必须进行更改时都非常不方便,因为我必须记住将此语句放在正确的位置,运行程序,然后手动将值复制回源代码(或实际上,只需自己输入更改即可)。
I am open to a better solution.我对更好的解决方案持开放态度。 Is there a language feature that provides the functionality I am looking for?
是否有提供我正在寻找的功能的语言功能?
Let TypeScript infer the type of data
, then extract the keys from the type it infers by using type data_key = keyof typeof data;
让 TypeScript 推断
data
的类型,然后使用type data_key = keyof typeof data;
从它推断的类型中提取键type data_key = keyof typeof data;
: :
const data = Object.freeze({
some: 123,
long: {"a":"b"},
list: ["c"],
of: "",
arbitrary: null,
things: 1.2,
});
type data_key = keyof typeof data;
function doWork(k: data_key) {
let value = data[k];
//...
}
How that works:它是如何工作的:
Object.freeze
with the keys some
, long
, list
, etc. Object.freeze
is defined as freeze<T>(o: T): Readonly<T>
¹ so it returns a Readonly
version of that same inferred type. Object.freeze
的对象初始值设定项的类型,键为some
、 long
、 list
等。 Object.freeze
被定义为freeze<T>(o: T): Readonly<T>
¹ 所以它返回相同推断类型的Readonly
版本。keyof
gets the keys of a type. keyof
获取类型的键。typeof
in this context is TypeScript's typeof
, not JavaScript's. typeof
在这个上下文中是 TypeScript 的typeof
,而不是 JavaScript 的。 In TypeScript, there are places it expects runtime value, and other places it expects compile-time types.keyof
's operand is a place where a compile-time type is expected, so typeof data
returns the compile-time type of data
, which is the Readonly version of the inferred type from freeze
(with the keys some
, long
, list
, etc.). keyof
的操作数是需要编译时类型的地方,因此typeof data
返回编译时类型的data
,这是从freeze
推断类型的只读版本(键为some
、 long
、 list
等.) (If you had x = typeof data
, that would be typeof
in a context where a runtime value is expected, so it would be JavaScript's typeof
, and x
would get the runtime value "object"
.) x = typeof data
,那么在需要运行时值的上下文中将是typeof
,因此它将是 JavaScript 的typeof
,而x
将获得运行时值"object"
。) ¹ There are actually three definitions of freeze
in lib.es5.d.ts
(one for arrays, one for functions, and one for all other kinds of objects; this is that last one). ¹
lib.es5.d.ts
中实际上有三种freeze
定义(一种用于数组,一种用于函数,一种用于所有其他类型的对象;这是最后一种)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.