Aid*_*din 16 arrays object typescript
当我在打字稿中使用Object.fromEntries(entries)orObject.entires(obj)来表示类型/常量entries数组或objt对象时,我会丢失类型any或广泛类型。
在某些情况下,我可以手动分配通用类型(例如Record<string, number>),但是设置每对/键的类型很繁琐。
这是我想要的一个例子。
const myArrayOfPairs = [["a", 5], ["b", "hello"], ["c", false]] as const;
// The type of the following is "any"
const myTypelessObject = Object.fromEntries(myArrayOfPairs);
// I want the type of this one to be: { a: 5; b: "hello"; c: false; }
const myTypedObject = createTypedObjectFromEntries(myArrayOfPairs);
Run Code Online (Sandbox Code Playgroud)
const myOldObject = {
x: 6,
y: "apple",
z: true
};
// The type of the following is [string, string | number | boolean][]
const myEntries = Object.entries(myOldObject);
// I want the type of this one to be more specific.
// i.e.: (["x", number] | ["y", string] | ["z", boolean])[]
const myTypedEntries = getTypedObjectEntries(myOldObject);
Run Code Online (Sandbox Code Playgroud)
Aid*_*din 13
这一个相对简单。使用[K in keyof OBJ_T]可以获取键,并OBJ_T[K]给出相对值。
这是它的一个简单实现:
// ~~~~~~~~~~~~~~~~~~~~~~~~ Utils ~~~~~~~~~~~~~~~~~~~~~~~~
type ObjectType = Record<PropertyKey, unknown>;
type PickByValue<OBJ_T, VALUE_T> // From /sf/answers/3860710031/
= Pick<OBJ_T, { [K in keyof OBJ_T]: OBJ_T[K] extends VALUE_T ? K : never }[keyof OBJ_T]>;
type ObjectEntries<OBJ_T> // From /sf/answers/4209946681/
= { [K in keyof OBJ_T]: [keyof PickByValue<OBJ_T, OBJ_T[K]>, OBJ_T[K]] }[keyof OBJ_T][];
// ~~~~~~~~~~~~~~~~~~~~ Typed Function ~~~~~~~~~~~~~~~~~~~~
function getTypedObjectEntries<OBJ_T extends ObjectType>(obj: OBJ_T): ObjectEntries<OBJ_T> {
return Object.entries(obj) as ObjectEntries<OBJ_T>;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~ Test ~~~~~~~~~~~~~~~~~~~~~~~~~
const myOldObject = {
x: 6,
y: "apple",
z: true
};
const myTypelessEntries = Object.entries(myOldObject); // type: [string, string | number | boolean][]
const myTypedEntries = getTypedObjectEntries(myOldObject);
type myTypedEntiresType = typeof myTypedEntries; // type: (["x", number] | ["y", string] | ["z", boolean])[]
Run Code Online (Sandbox Code Playgroud)
TS游乐场。请注意,您需要es2019成为 Configs 中的目标。
这是一个更具挑战性的事情。
您需要首先使用 提取内部数组对infer,然后使用通用实用UnionToIntersection程序类型合并结果。
这是我能想到的最好的:
// ~~~~~~~~~~~~~~~~~~~~~~~~ Utils ~~~~~~~~~~~~~~~~~~~~~~~~
// Data Types
type EntriesType = [PropertyKey, unknown][] | ReadonlyArray<readonly [PropertyKey, unknown]>;
// Existing Utils
type DeepWritable<OBJ_T> = { -readonly [P in keyof OBJ_T]: DeepWritable<OBJ_T[P]> };
type UnionToIntersection<UNION_T> // From /sf/answers/3526270051/
= (UNION_T extends any ? (k: UNION_T) => void : never) extends ((k: infer I) => void) ? I : never;
// New Utils
type UnionObjectFromArrayOfPairs<ARR_T extends EntriesType> =
DeepWritable<ARR_T> extends (infer R)[] ? R extends [infer key, infer val] ? { [prop in key & PropertyKey]: val } : never : never;
type MergeIntersectingObjects<ObjT> = {[key in keyof ObjT]: ObjT[key]};
type EntriesToObject<ARR_T extends EntriesType> = MergeIntersectingObjects<UnionToIntersection<UnionObjectFromArrayOfPairs<ARR_T>>>;
// ~~~~~~~~~~~~~~~~~~~~~ Typed Functions ~~~~~~~~~~~~~~~~~~~~~
function createTypedObjectFromEntries<ARR_T extends EntriesType>(arr: ARR_T): EntriesToObject<ARR_T> {
return Object.fromEntries(arr) as EntriesToObject<ARR_T>;
}
// ~~~~~~~~~~~~~~~~ Test for entries->object ~~~~~~~~~~~~~~~~~
const myArrayOfPairs = [["a", 5], ["b", "hello"], ["c", false]] as const;
const myTypelessObject = Object.fromEntries(myArrayOfPairs); // type: any
const myTypedObject = createTypedObjectFromEntries(myArrayOfPairs);
type myTypedObjectType = typeof myTypedObject; // type: { a: 5; b: "hello"; c: false; }
Run Code Online (Sandbox Code Playgroud)
现在,使用新的 .TypeScript 5 可以更轻松地实现这一点const Type Parameter。
//\n// Object.fromEntries\n//\n\nconst typeSafeObjectFromEntries = <\n const T extends ReadonlyArray<readonly [PropertyKey, unknown]>\n>(\n entries: T\n): { [K in T[number] as K[0]]: K[1] } => {\n return Object.fromEntries(entries) as { [K in T[number] as K[0]]: K[1] };\n};\n\nconst myObject = typeSafeObjectFromEntries([\n ["a", 5],\n ["b", "hello"],\n ["c", false],\n]); // { a: 5; b: "hello"; c: false } \xe2\x9c\x85\n\n//\n// Object.entries\n// (add const param for less broader types (ie. string -> "apple") -> const T extends Record<PropertyKey, unknown>)\n//\n\nconst typeSafeObjectEntries = <T extends Record<PropertyKey, unknown>>(\n obj: T\n): { [K in keyof T]: [K, T[K]] }[keyof T][] => {\n return Object.entries(obj) as { [K in keyof T]: [K, T[K]] }[keyof T][];\n};\n\nconst myEntries = typeSafeObjectEntries({ x: 6, y: "apple", z: true });\n// ["x", number] | ["y", string] | ["z", boolean])[] \xe2\x9c\x85\n// with const param: (["x", 6] | ["y", "apple"] | ["z", true])[] \xe2\x9c\x85\nRun Code Online (Sandbox Code Playgroud)\n\n