Typescript:映射键的类型与值的类型相同,但不限制键的类型
有没有办法进行以下的打字检查Typescript:映射键的类型与值的类型相同,但不限制键的类型,typescript,dictionary,generics,Typescript,Dictionary,Generics,有没有办法进行以下的打字检查 const map = new Map() map.set('stringkey', 'stringvalue') // OK map.set(5, 10) // OK const objectKey = { name: 'bob' } map.set(objectKey, { name: 'alice' }) // OK const stringValue: string = map.get('stringkey') // OK, but is typed a
const map = new Map()
map.set('stringkey', 'stringvalue') // OK
map.set(5, 10) // OK
const objectKey = { name: 'bob' }
map.set(objectKey, { name: 'alice' }) // OK
const stringValue: string = map.get('stringkey') // OK, but is typed as 'any'
const objectValue: { name: string } = map.get(objectKey) // OK, but is typed as 'any'
map.set('string', 5) // Error
map.set({ name: 'bob' }, { food: 'cake' }) // Error
使用默认值
const map = new Map<any, any>()
const map=new map()
可以工作,但在访问值时不会提供有用的类型,因为它们都是按任何类型键入的。这很有趣。我认为最好的方法是声明您自己的接口,它代表您的
映射的特定变体
:
interface SameKeyValueMap {
clear(): void;
delete(key: any): boolean;
forEach(
callbackfn: <T>(value: T, key: T, map: SameKeyValueMap) => void, thisArg?: any
): void;
get<T>(key: T): T | undefined;
has(key: any): boolean;
set<T>(key: T, value: T): this;
readonly size: number;
}
const map: SameKeyValueMap = new Map();
必须更改以下内容,因为get()
可以返回未定义的:
const stringValue: string | undefined = map.get('stringkey')
const objectValue: { name: string } | undefined = map.get(objectKey)
下面是您想要的错误:
map.forEach((x, y) => (console.log(x === y))); // OK
map.set('stringkey', 'stringvalue') // OK
map.set(5, 10) // OK
const objectKey = { name: 'bob' }
map.set(objectKey, { name: 'alice' }) // OK
map.set('string', 5) // Error
但以下不是错误:
map.set({ name: 'bob' }, { food: 'cake' }) // accepted?
如果你看,那是因为类型T
被推断为{name:string,food?:undefined}{name?:undefined,food:string}
。这与您传入的值是一致的。那样的话,类型推断有点像黑色艺术
解决这个问题的一种方法是将T
的一个推理站点的set()
签名更改为。这样一来,T
将仅从其中一个参数推断,而不是同时从两个参数推断。像这样:
interface SameKeyValueMap {
clear(): void;
delete(key: any): boolean;
forEach(
callbackfn: <T>(value: T, key: T, map: SameKeyValueMap) => void, thisArg?: any
): void;
get<T>(key: T): T | undefined;
has(key: any): boolean;
set<T>(key: T, value: T & {}): this; // lowered priority of value
readonly size: number;
}
在这种情况下,T
被推断为{name:string}
,{food:'cake'}
不可分配给它。所以这是一个错误
希望有帮助。祝你好运 虽然现代JS实现了一个可以接受对象作为键的映射,但它的行为可能并不像您期望的那样。如果键不是字符串或数字,则按标识(而不是值)比较键。换句话说,键将与==
操作符进行比较,具有相同键和值的两个对象不一定相互==
。
map.set({ name: 'bob' }, { food: 'cake' }) // error