-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Object.entries
broken with object literals
#56
Comments
We are using the following workaround in our projects: interface ObjectConstructor {
entries<T extends object>(source: T): [keyof T & string, T[keyof T]][];
} |
FWIW, I suggested the following implementations in #31 (comment): type KeyToString<K extends PropertyKey> = K extends string ? K : K extends number ? `${K}` : never;
interface ObjectConstructor {
keys<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): KeyToString<K>[];
values<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): V[];
entries<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): [KeyToString<K>, V][];
} Where the |
I see how this is inconvenient, but I don't think this can be made better without breaking type safety. Specifically, code like below would break type safety if you are using that workaround. type A = { a: number; b: number };
const obj = { a: 1, b: 2, c: "Hey!" };
const obj2: A = obj;
const entries = Object.entries(obj2);
// ^? To mitigate this we need exact types, which isn't supported by TS yet. That said, I think I need more time to evaluate the solution proposed by @ehoogeveen-medweb here. |
Ah I see. And this has been discussed in #2 already (I did not scan the closed issues before ...) |
I think the fact that typescript allows excess properties makes it fundamentally impossible to have "optimistic" signatures that are fully safe: type KeyToString<K extends PropertyKey> = K extends string ? K : K extends number ? `${K}` : never;
declare function entries<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): [KeyToString<K>, V][];
type A = { a: number; b: number };
const obj1 = { a: 1, b: 2, c: "Hey!" } as const;
const obj2: A = obj1;
const entries1 = entries(obj1); // ["a" | "b" | "c", 2 | 1 | "Hey!"][]
const entries2 = entries(obj2); // [keyof A, number][]
for (const [key, value] of entries2) {
// TS2367: This comparison appears to be unintentional because the types 'keyof A' and '"c"' have no overlap.
if (key == 'c') {
// Excess property with unknown value type
}
} So theoretically |
Er, I guess not |
The value type of object literals becomes
unknown
.The text was updated successfully, but these errors were encountered: