Skip to content

Design Meeting Notes, 8/21/2020 #40184

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
DanielRosenwasser opened this issue Aug 21, 2020 · 1 comment
Closed

Design Meeting Notes, 8/21/2020 #40184

DanielRosenwasser opened this issue Aug 21, 2020 · 1 comment
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Broken Method Calls on Unions

#40157

  • Added a new signature to every that takes a type predicate.
  • Is narrowing with every more important? Or is every on unions more important?
  • What if we had a way of saying every type is a predicate for value is unknown.
  • Feels bad, but lots of people have asked for the every overload.
  • Only one complaint since before the beta.
  • Conclusion: Probably will not back this change out.

Strict Environment Checks

https://gist.github.com/RyanCavanaugh/702ebd1ca2fc060e58e634b4e30c1c1c

  • We had placeholder types as a proposal for a while, but the problem is that anyone who doesn't use placeholder types and just uses a global library can "spoil the pot".
  • One big issue: global pollution
    • Someone needs Buffer. Now everyone gets Buffer and whatever else comes along.
  • Another: augmentation pollution
    • "I need ES6 types like Map" implies "I need all of ES6"
    • Placeholder types are good for this, but a lot of this could be solved without placeholder types.
  • Placeholder types also only worked with separate projects when you need a mixed-environment project.
  • Idea: --strictEnvironment
    • /// <reference lib="es6" /> only pulls in lib.es6.types.d.ts (forward declarations for types)
    • Each file's global scope is determined individually
  • What about polyfills? How do you get this to work for people?
    • It's sort of intentional - automagic inclusion introduces the pain, you have to opt in.
  • It's not quite as non-trivial to construct these environments as we might think - global merging is recursive.
  • There's an effort to not transitively include everything, but all of the /// <reference lib /> directives contain more /// <reference lib />.
  • Conclusion: interested in feedback, need to think more on this.

Key Mapping in Mapped Types

#12754

  • The feature ask is "I want to be able to change the name of a property name in a mapped type.

  • Lots of demand, but currently not (easily?) possible today.

    • Especially not when generating new keys
  • Idea was maybe let people remap the keys with an as or something, give users a template-string-like syntax

    type Events<T> = {
        [K in keyof T as `on${K}Changed`]: (value: T[K]) => void
    };
  • Also would need some sort of operator to capitalize the first character of a string (e.g. capitalize K).

  • Would eventually be expected as a top-level concatenation type operator.

    • `${"foo"} to ${"bar"}` is "foo to bar"

    • Distributive

      // "top-left" | "top-center" | "top-right" | "middle-left" ...
      type Loc = `${"top" | "middle" | "bottom"}-${"left" | "center" | "right"}`;
  • Current thinking is these template types work on

  • What about existing code that uses templates?

    • <T extends string>(x: T) => `hello ${x}` // is this 'string' or `hello ${T}`?
  • Can we do inference?

    • Examples of lodash's get operator.
    • The real get doesn't just do dots, they also indexed accesses.
      • So the naive version of this is wrong.
    • Should you just have a split operator?
  • As you get farther into this, you start to see "this might not be enough"

    • You start to want a regex!
  • Out of time, but looking for feedback as this gets prototyped.

Contextually Type Operands of await in a StatementExpression

#39817

  • void parameters become optional, want to funnel void to resolve from the outside on Promises.
  • Idea is await in certain contexts gets ignored; so just make the contextual type for the expression to await Promise<void>.
  • Conclusion: want to experiment with something more general that starts out with void in the top-level, gets transformed in the await.
@danvk
Copy link
Contributor

danvk commented Aug 29, 2020

Not saying it's pretty, but you can do key remapping using the Unionize/Objectify trick, so long as you have a restricted vocabulary of terms:

interface Person {
  name: string;
  age: number;
  greet: () => string;
}

const rename = {
  name: 'NAME',
  age: 'AGE',
  greet: 'GREET',
} as const;
type Rename = typeof rename;

type CapitalizeKV<KV extends KVPair> = KV extends {k: infer K, v: infer V} ? K extends keyof Rename ? {k: Rename[K], v: V} : never : never;
type AllCaps<T extends object> = Objectify<CapitalizeKV<Unionize<T>>>;

type CapitalPerson = AllCaps<Person>;
// type is {
//   NAME: string;
//   AGE: number;
//   GREET: () => string;
// }

(full playground)

String concatenation would be nice, but a more general way to map between string literal types (#6579) would be even nicer!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

2 participants