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.
>Solution :
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'