Home > Back-end >  Why does Object.entries return a union type?
Why does Object.entries return a union type?

Time:06-05

I'm using the following code, with typescript 4.7.3, and don't understand why the type of amount isn't PositiveNumber.

export type PositiveNumber = number & { __type: 'PositiveNumber' }
export type PointsByAbbrev = Record<string, PositiveNumber> & { __type: 'PointsByAbbrev' }
export const isPointsByAbbrev = (value: Record<string, number> | null | undefined): value is PointsByAbbrev => hasValue(value) && Object.values(value).every(x => x >= 0)

class Foo {
    data!: PointsByAbbrev
    
    generate(input: Record<string, number>) {
        if (isPointsByAbbrev(input))
            this.data = input
    }

    someMethod(): void {
        Object.entries(this.data).forEach(([abbrev, amount]) => {
        })
    }
}

According to the compiler, the type of amount is PositiveNumber | "PointsByAbbrev"

I'm assigning the data via a process like the generate method shows where I pass the input through the type guard and then assign if true.

CodePudding user response:

It looks like you're trying to do some variety of newtype pattern with that __type field, but that doesn't make the field any less real. As far as Typescript is concerned, __type is a valid slot on your object and its type is 'PointsByAbbrev'. The type of this.data is

Record<string, PositiveNumber> & { __type: 'PointsByAbbrev' }

The fields of Record<string, PositiveNumber> have type PositiveNumber, and the fields of { __type: 'PointsByAbbrev' } have type 'PointsByAbbrev', so the entire intersection type's fields have type PositiveNumber | 'PointsByAbbrev'

  • Related