Skip to content

Design Meeting Notes, 1/22/2021 #42589

Closed
Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Template String Types for Template Expressions

(continued)

  • Strong feelings on this?

    • Seems better, and more consistent, with templates with no holes.
    • As soon as you added holes in positions, then you lose it.
    • So part of the idea is we're trying to faithfully reflect what's happening in the type system.
  • + concatenations don't do this though - that's very inconsistent.

  • If we were to introduce + for any T and U.

  • We don't support algebraic operators in general.

    const a: 42 = 42;
    const b: 3  = 3;
    const c = a + b
  • In DefinitelyTyped, we recently had a PR with a huge number of strings - one could argue that's strictly better.

  • Should a new programmer have to see this behavior?

  • New programmer will usually see a union type.

    • Will sometimes see a template with an interpolated string though!
  • There's a widening/non-widening form, right?

  • Consistency arguments don't exactly feel useful because you want the literal type so you can compare for literal unions.

    • When you have an infinite set...that feels somewhat less useful.
    • Consistency vs. usability argument, usability feels more compelling to me.
  • Could imagine "only create a literal type if it's finite"

    • Still hard to explain "if you fill your hole with a string, you won't get a literal-ish type."
  • Maybe the most minimal change is to make return statements do different widening.

  • Can always opt in with as const with old behavior.

  • There is some sentiment that the behavior is good; but should just make concessions to widening on function returns.

    // This should probably keep working like it does post-PR:
    let a = 12;
    const lit = `${a}px`;
    usePxValue(lit);
    const obj = {
        lit
    };
  • But feels strange, that if you wrote this as makePx, and we widened for you, that'd be bad.

  • unique symbols widen to symbols.

  • Seems like these should work the same.

    let a = 12;
    const c = `${x}px`;
    
    function makePxValue1(x: number) {
        return `${x}px`;
    }
    
    function makePxValue2(x: number) {
        const c = `${x}px`;
        return c;
    }
  • If we revert, we can avoid all these contextual rules.

    • Only time we infer literal types is if they're finite.
    • Also, can maintain the string slots when contextually typed.
  • Seems like reverting is a reasonable option, so you'd just end up with string unless you write as const - same way with arrays/object literals.

  • What kind of inferences would we need to make this better? Seems like these are desirable.

    • Well you have to speculate with these super-specific types - that's why we have widening. So you don't really know.
    • We need to see where/when/how types are mutated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions