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'