Lio*_*Tay 2 generics dictionary typescript
有没有办法进行以下类型检查?
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
Run Code Online (Sandbox Code Playgroud)
使用默认值
const map = new Map<any, any>()
Run Code Online (Sandbox Code Playgroud)
有效,但在访问值时没有提供有用的类型,因为它们都被键入为 any。
这很有趣。我认为您继续的最佳方法是声明您自己的接口,它代表您的特定变体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();
Run Code Online (Sandbox Code Playgroud)
这主要以您想要的方式工作:
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
Run Code Online (Sandbox Code Playgroud)
以下必须更改,因为get()can return undefined:
const stringValue: string | undefined = map.get('stringkey')
const objectValue: { name: string } | undefined = map.get(objectKey)
Run Code Online (Sandbox Code Playgroud)
这是你想要的错误:
map.set('string', 5) // Error
Run Code Online (Sandbox Code Playgroud)
但以下不是错误:
map.set({ name: 'bob' }, { food: 'cake' }) // accepted?
Run Code Online (Sandbox Code Playgroud)
如果你看一下,那是因为类型T被推断为{name: string, food?: undefined} | {name?: undefined, food: string}. 这与您传入的值是一致的。类型推断在这种情况下有点像黑色艺术。
尝试处理的一个方法是改变set()签名,以降低优先级的推断位点之一T。这种方式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;
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效:
map.set({ name: 'bob' }, { food: 'cake' }) // error
Run Code Online (Sandbox Code Playgroud)
在这种情况下,T被推断为{name: string}并且{food: 'cake'}不可分配给它。所以这是一个错误。
希望有帮助。祝你好运!