Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Design Meeting Notes, 8/21/2020 #40184

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!

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

No branches or pull requests

2 participants