#Union isn't narrowing by typeof?!
1 messages · Page 1 of 1 (latest)
Preview:```ts
class Foo {
foo: number
constructor() {
this.foo = 3
}
}
type Bar =
| {
signer: string
asdf: string
}
| {
signer: Foo
}
function test() {
const token = {
signer: '',
asdf: ''
} satisfies Bar as Bar
if(typeof token.signer === 'string') {
...```
performing a check on one property does not change the type of the original object in TS
the TS compiler isn't smart enough for that yet, or at least it can't really be proven easily using types, even if it seems logical to us
instead, try creating a new variable and using that one
also, satisfies Bar as Bar is kinda useless
you could/should put the proper type on the variable directly
const token: Bar = { ... }
haha i did that because typing as the var didn't work - sec
that's provably untrue, tho - sec
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
@whole musk Here's a shortened URL of your playground link! You can remove the full link from your message.
Preview:```ts
class Foo {
foo: number
constructor() {
this.foo = 3
}
}
type Bar =
| {
disc: "x"
signer: string
asdf: string
}
| {
disc: "y"
signer: Foo
}
function test() {
const token = {
disc: "x",
signer: '',
...```
typeof token.signer === 'string' makes sense to us
for for TS, you aren't acting on the token object
that's using discriminators, it's another case
right - so i'm wondering why using a discriminator can narrow the type, but a typeof can't, when the result is the same - i'm performing some runtime check to narrow a type
is it the indirection of the typeof operation?
because by using a discriminator, you actually use exhaustion checking
it must be one of the finite possibilities of the union
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
@whole musk Here's a shortened URL of your playground link! You can remove the full link from your message.
Preview:```ts
class Foo {
foo: number
constructor() {
this.foo = 3
}
}
type Bar =
| {
disc: "x"
signer: string
}
| {
disc: "y"
signer: Foo
}
function test() {
const token: Bar = {
disc: "x",
signer: "",
}
type BBBB = typeof token.signer
...```
however, when not using those, it's just regular narrowing
and narrowing a property that way does not impact the parent object
right - but a typeof operation does the same thing.
I'm just wondering if it's like, a bug, or an intention design decision, since checking equality and doing a typeof are only different in that the typeof is an extra operation
got it
makes sense
since you are not doing the narrowing on the parent object directly
not really a bug
not a decision either
just that there are different ways to do narrowing
some are more appropriate than others in certain cases
i mean, yeah - discriminants with ===, in, typeof but only on primitives..
feels like an outlier that typeof for a discriminant doesn't work
it's not really typeof vs ===
it's "equality narrowing of a property" vs "exhaustiveness checking"
each type of narrowing have pros and cons
sometimes many ways are or look possible
yeah, fair enough
you can alwayse use casts if you are certain a value will be a certain type and the compiler isn't smart enough to narrow it as of now
i'd mark this solved, then
the only thing i have left is that the satisfies.. as.. is actually needed :P
really? 
Preview:```ts
class Foo {
foo: number
constructor() {
this.foo = 3
}
}
type Bar =
| {
disc: "x"
signer: string
}
| {
disc: "y"
signer: Foo
}
function test() {
const token: Bar = {
disc: "x",
signer: "",
}
type BBBB = typeof token.signer
...```
check it out
ts 5.0 tries to be clever
and auto-narrows if i just use a type on the var
because to me it really looks like it's the same thing as const token: Bar
nah nah check my example
since TS still checks the object meet's Bar requirements to be assigned, and doesn't infer the exact type
ah, but it does infer the exact type in 5.0 😁
or, well, at least narrows it to one union arm
hum, that's weird 
ain't it just 🤔