-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
Should an Optional Chain Always Add undefined
to the Type?
const arr = [1, 2, 3, 4, 5]
const j = Math.random() * 1000 % 1;
const k = arr[j]?.toFixed();
-
If index signatures included
undefined
, you'd getundefined
.- But this can go beyond that case.
-
Defensive code in general.
-
But we have plenty of places where we don't make
||
conservative.// Inferred to `number[]` because we // don't assume it *could* be null/undefined function foo(x: number[]) { return x || "hello" }
-
Okay, but are you going to trust that the user wrote
?.
for a reason, or assume we have a perfect type system? -
Seems like the indexing case is hard to explain to users
- Okay, but maybe we could fix the indexing case?
- Really a separate issue
- Okay, but maybe we could fix the indexing case?
-
Are people encountering this?
- It's a new feature, and the longer we wait, the more we may hear about this.
-
Why would you write
?.
on a defined type unless you planned to immediately handle them?- The indexing case?
- Then let's solve the indexing case.
-
Should we also change
||
and&&
?- Maybe!
- What!? This behavior is so old, who exactly are you helping by changing that?
- Pretty sure we need code like this to work because of how narrowing within arrays works today.
-
Discussion inconclusive
Augmenting Keys
-
Some demand to do two things:
- Slicing/dicing strings to convert from/to camelCase, kebab-case, etc.
- Filtering out types
- And maybe just concatenating literals
-
Would be nice to write
type Foo<T> = { [K in keyof T as StringConcat<"get-", K>]: T[K] };
-
Could you do something like the following?
type Foo<T> = { [K in StringConcat<"get-", keyof T>]: T[K] };
-
-
Created a prototype that wires up a bunch of type aliases that have special behavior:
type StringToUpper<K> = ...; // StringToUpper<"Foo"> -> "FOO" type StringToLower<K> = ...; // StringToLower<"Foo"> -> "foo" // StringSlice<"hello", 1> -> "ello" type StringSlice<K, Start extends number, End extends number> = ...; // StringConcat<"foo", "bar"> -> "foobar" type StringConcat<K1, K2> = ...; // StringMatch<"foo" | "bar" | "baz", "a"> -> "bar" | "baz" type StringMatch<K, Pattern extends string> = ...;
-
Won't these cause a lot of exponential explosions in the type system?
- Sure, but we already have those.
- Yes, But we're already trying to grapple with them.
- Sure, but we already have those.
-
Can we not use type aliases for everything here?
- Not clear that it's better.
- Strange that there's a magical name that has behavior instead of something core to the language.
- But creating more operators/keywords would be a lot of new work in the parser.
-
Many of these aren't useful on generics - what if we just let people write actual code to do this?
- Now you have to have a API on our type system.
-
Do we think this is something we want to solve?
- Need to see the use-cases - what are people doing today?
- Code generators? Index signatures?
- Can't necessarily say "yes", but probably not near-term. We should be focusing on speed.
- Need to see the use-cases - what are people doing today?