I've found a problem using PartialDeep of interfaces that override the signature of Object prototype properties like valueOf:
import { PartialDeep } from "type-fest";
interface OverrideValueOf {
str: string;
valueOf(): number;
}
/*
{ str: string } is a partial of OverrideValueOf so I expect it to work but it errors with:
Types of property 'valueOf' are incompatible.
Type '() => Object' is not assignable to type '() => number'.
Type 'Object' is not assignable to type 'number'.
*/
const partial: PartialDeep<OverrideValueOf> = {
str: 'string'
};
Projects like discord.js have interfaces like that one where valueOf
returns a string instead of an object meaning that I can't use them with PartialDeep.
Since PartialDeep doesn't allow me to specify valueOf:
interface MyInterface {
str: string;
}
// ERROR
// Object literal may only specify known properties, and 'valueOf' does not exist in type 'PartialObjectDeep<MyInterface>'.
const myInt: PartialDeep<MyInterface> = {
str: 'string',
valueOf: () => ({})
};
I expected it to never interfere with an interface.
Expected:
No error when interfaces change signatures of Object prototype properties
Actual:
Error of incompatibility between Object prototype property and interface property with the same name
Proposed solution:
I have a solution that fixes this problem but to be honest my guess is that it breaks something else... but I've found out that we can change the PartialDeep type definition like this:
// Current
export type PartialDeep<T> = T extends Primitive
? Partial<T>
: T extends Map<infer KeyType, infer ValueType>
? PartialMapDeep<KeyType, ValueType>
: T extends Set<infer ItemType>
? PartialSetDeep<ItemType>
: T extends ReadonlyMap<infer KeyType, infer ValueType>
? PartialReadonlyMapDeep<KeyType, ValueType>
: T extends ReadonlySet<infer ItemType>
? PartialReadonlySetDeep<ItemType>
: T extends (...args: any[]) => unknown
? T | undefined
: T extends object
? PartialObjectDeep<T>
: unknown;
// Updated
export type PartialDeep<T> = T extends Primitive
? Partial<T>
: T extends Map<infer KeyType, infer ValueType>
? PartialMapDeep<KeyType, ValueType>
: T extends Set<infer ItemType>
? PartialSetDeep<ItemType>
: T extends ReadonlyMap<infer KeyType, infer ValueType>
? PartialReadonlyMapDeep<KeyType, ValueType>
: T extends ReadonlySet<infer ItemType>
? PartialReadonlySetDeep<ItemType>
: T extends object
? PartialObjectDeep<T>
: T extends (...args: any[]) => unknown // this condition is now after T extends object
? T | undefined
: unknown;
Let me know
Versions:
type-fest: 0.16.0
typescript: 3.9.7
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too