打字稿:如何提取常量对象的值类型并将它们用作新类型的键?
Typescript: How to extract the value types of a const object and use them as keys in a new type?
我想获取一个常量对象,比如 {key1: 'value1', key2: value2'} as const
,并将其值转换为键并在类型为 {value1: number; value2: number}
的新对象中使用它。我想在一个函数中执行此操作,并且我希望函数被正确键入。
下面是我要开始工作的代码。当我尝试将 Partial<Blah>
类型的变量转换为 Blah
时发生错误。有人可以解释为什么会发生这种情况,以及是否有办法做我想做的事情?谢谢!
type BaseObject = Record<string, string>;
type ValuesAsKeys<T extends BaseObject> = {
[K in keyof T as T[K]]: number;
};
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
const x: Partial<ValuesAsKeys<T>> = {};
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
// This line doesn't work
return x as ValuesAsKeys<T>;
}
// Example use case
const obj = {key1: 'value1', key2: 'value2'} as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}
// Everything below here works
// Only including this because I'm contrasting this code with the code above.
type KeysAsKeys<T extends BaseObject> = {
[K in keyof T]: number;
};
function useKeysAsKeys<T extends BaseObject>(arg: T): KeysAsKeys<T> {
const x: Partial<KeysAsKeys<T>> = {};
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
return x as KeysAsKeys<T>;
}
使用 reduce
的显式 return 类型几乎总是行不通,因为 initial
值在每次迭代时都会改变。
为了让它工作,最好重载你的函数:
type BaseObject = Record<string, string>;
type ValuesAsKeys<T extends BaseObject> = {
[K in keyof T as T[K]]: number;
};
type Values<T> = T[keyof T]
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T>
function useValuesAsKeys<T extends BaseObject>(arg: T) {
return (Object.values(arg) as Array<Values<T>>).reduce((acc, elem) => ({
...acc,
[elem]: 1
}), {})
}
// Example use case
const obj = { key1: 'value1', key2: 'value2' } as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}
result.value1 //ok
我仍然不确定为什么将 Partial<Blah>
强制转换为 Blah
在这种情况下不起作用,但这段代码有效并且对我来说足够类型安全:
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
const x = {} as ValuesAsKeys<T>;
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
return x;
}
我想获取一个常量对象,比如 {key1: 'value1', key2: value2'} as const
,并将其值转换为键并在类型为 {value1: number; value2: number}
的新对象中使用它。我想在一个函数中执行此操作,并且我希望函数被正确键入。
下面是我要开始工作的代码。当我尝试将 Partial<Blah>
类型的变量转换为 Blah
时发生错误。有人可以解释为什么会发生这种情况,以及是否有办法做我想做的事情?谢谢!
type BaseObject = Record<string, string>;
type ValuesAsKeys<T extends BaseObject> = {
[K in keyof T as T[K]]: number;
};
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
const x: Partial<ValuesAsKeys<T>> = {};
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
// This line doesn't work
return x as ValuesAsKeys<T>;
}
// Example use case
const obj = {key1: 'value1', key2: 'value2'} as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}
// Everything below here works
// Only including this because I'm contrasting this code with the code above.
type KeysAsKeys<T extends BaseObject> = {
[K in keyof T]: number;
};
function useKeysAsKeys<T extends BaseObject>(arg: T): KeysAsKeys<T> {
const x: Partial<KeysAsKeys<T>> = {};
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
return x as KeysAsKeys<T>;
}
使用 reduce
的显式 return 类型几乎总是行不通,因为 initial
值在每次迭代时都会改变。
为了让它工作,最好重载你的函数:
type BaseObject = Record<string, string>;
type ValuesAsKeys<T extends BaseObject> = {
[K in keyof T as T[K]]: number;
};
type Values<T> = T[keyof T]
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T>
function useValuesAsKeys<T extends BaseObject>(arg: T) {
return (Object.values(arg) as Array<Values<T>>).reduce((acc, elem) => ({
...acc,
[elem]: 1
}), {})
}
// Example use case
const obj = { key1: 'value1', key2: 'value2' } as const;
const result = useValuesAsKeys(obj); // Type of result is {value1: number; value2: number}
result.value1 //ok
我仍然不确定为什么将 Partial<Blah>
强制转换为 Blah
在这种情况下不起作用,但这段代码有效并且对我来说足够类型安全:
function useValuesAsKeys<T extends BaseObject>(arg: T): ValuesAsKeys<T> {
const x = {} as ValuesAsKeys<T>;
for (const value of Object.values(arg) as Array<T[keyof T]>) {
x[value] = 1;
}
return x;
}