使用键值来查找变量,在导入时将其作为命名空间。

huangapple go评论66阅读模式
英文:

Use key value to look up variable when doing import as namespace

问题

I understand your request, here's the translated content:

也许我正在尝试的操作是不可能的,或者我采用了错误的方法,但是否可以使用字符串来在导入的命名空间上进行查找?

如果我有一个文件:my_file.ts,其内容如下所示:

export const MyThing: CustomType = {
    propertyOne: "name",
    propertyTwo: 2
}
export const AnotherThing: CustomType = {
    propertyOne: "Another",
    propertyTwo: 3
}

然后我有一个文件要导入所有这些内容,但需要根据一个字符串动态查找并使用它们:

import * as allthings from "dir/folder/my_file";

function doStuff() {
   let currentThing = allthings['MyThing']; // 可行
   let name = 'MyThing';
   let currentThing2 = allthings[name]; // 无法使用
}

这里出现的错误是:

元素隐式具有“any”类型,因为类型为“string”的表达式不能用于索引类型为“typeof import("dir/folder/my_file")”的类型。在类型“typeof import("dir/folder/my_file")”上找不到具有参数类型“string”的索引签名。

为什么字面字符串有效,而类型为字符串的变量无法使用呢?

英文:

Perhaps what I'm asking to do is impossible, or I'm taking the wrong approach but is it possible to use a string to do a lookup on an imported namespace?

If I have a file: my_file.ts and its contents are many of these:

export const MyThing: CustomType = {
    propertyOne: "name",
    propertyTwo: 2
}
export const AnotherThing: CustomType = {
    propertyOne: "Another",
    propertyTwo: 3
}

Then I have a file that is going to import all these, but needs to find and use them dynamically based on a string:

import * as allthings from "dir/folder/my_file"


function doStuff() {
   let currentThing = allthings['MyThing']; // works
   let name = 'MyThing';
   let currentThing2 = allthings[name]; // doesnt work

}

The error I get here is:

> Element implicitly has an 'any' type because expression of type
> 'string' can't be used to index type 'typeof
> import("dir/folder/my_file")'. No index signature with a parameter of
> type 'string' was found on type 'typeof import("dir/folder/my_file")'.

Why does the literal string work but not a variable of type string?

答案1

得分: 3

The literal string doesn't work because someone could reassign any string to your let name variable.

如果使用字面字符串,由于任何人都可以重新分配任何字符串给你的 let name 变量,所以它不起作用。

It will work if your string is const. Casting it is possible:

如果你的字符串是 const,它将起作用。也可以进行强制转换:

let name = 'MyThing' as const;

But you should just define a const variable which has the same effect. There's no reason to define a variable with let unless you intend to change it.

但是你应该只定义一个具有相同效果的 const 变量。除非你打算更改它,否则没有理由使用 let 来定义变量。

const name = 'MyThing';

See this TS playground example

如果你不知道键值提前,那么如果 my_file 中的所有对象都是相同类型(CustomType),那么你可以安全地使用 keyof typeof allthings 作为类型。

For these enum-like objects, you can use satisfies Record<string, MyType> to enforce they are all of the same type.

对于这些类似枚举的对象,你可以使用 satisfies Record<string, MyType> 来强制它们都是相同类型的。

英文:

The literal string doesn't work because someone could reassign any string to your let name variable.

It will work if your string is const. Casting it is possible:

let name = &#39;MyThing&#39; as const;

But you should just define a const variable which has the same effect. There's no reason to define a variable with let unless you intend to change it.

const name = &#39;MyThing&#39;;

See this TS playground example

If you don't know the key ahead of time, then if all the objects in my_file are of the same type (CustomType), then you can safely use keyof typeof allthings as the type

export const allthings = {
  MyThing: {
    propertyOne: &quot;name&quot;,
    propertyTwo: 2
  },
  AnotherThing: {
    propertyOne: &quot;Another&quot;,
    propertyTwo: 3
  }
};

type CustomType = typeof allthings[keyof typeof allthings];


function getValue(key: keyof typeof allthings): CustomType {
    return allthings[key]; 
}

See TS example

For these enum like objects, you can use satisfies Record&lt;string, MyType&gt; to enforce they are all of the same type

interface CustomType {
  propertyOne: string,
  propertyTwo: number
}

const allthings = {
  MyThing: {
    propertyOne: &quot;name&quot;,
    propertyTwo: 2
  },
  AnotherThing: {
    propertyOne: &quot;Another&quot;,
    propertyTwo: 3
  }
} satisfies Record&lt;string, CustomType&gt;;


function getValueFromAllThings(key: keyof typeof allthings): CustomType {
    return allthings[key]; 
}

答案2

得分: 0

I reread a similar question here: https://stackoverflow.com/questions/57086672/element-implicitly-has-an-any-type-because-expression-of-type-string-cant-b

And was finally able to get it to work by doing this:

import * as allthings from "dir/folder/my_file";

function doStuff() {
   let currentThing = allthings['MyThing']; // works
   let name = 'MyThing';
   let currentThing2 = allthings[name as keyof typeof allthings]; // does work
}
英文:

I reread a similar question here: https://stackoverflow.com/questions/57086672/element-implicitly-has-an-any-type-because-expression-of-type-string-cant-b

And was finally able to get it to work by doing this:

import * as allthings from &quot;dir/folder/my_file&quot;


function doStuff() {
   let currentThing = allthings[&#39;MyThing&#39;]; // works
   let name = &#39;MyThing&#39;;
   let currentThing2 = allthings[name as keyof typeof allthings]; // does work

}

huangapple
  • 本文由 发表于 2023年5月22日 22:07:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定