microsoft / microsoft/TypeScript

Safe type assertion (upcast / widening) operator

Aperta
#56,235 11 commenti 13 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Awaiting More Feedback Suggestion
Lingua principale
Go
Stelle
111k
Fork
14.4k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

🔍 Search Terms

as, satisfies, type assertion, type casting

✅ Viability Checklist
  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion

I suggest adding a safe type assertion operator, a kind of middle ground between current as and satisfies.

  • Like as, it should cast the expression to the asserted type
  • Like satisfies, it should only allow assertion if the asserted type is wider than the expression type

Here's what it might look like:

type Foo = { a: number }

const foo1 = { a: 1 } as! Foo // OK. foo1: Foo

const foo2 = { a: 1, b: 2 } as! Foo // OK, foo2: Foo

const foo3 = { b: 2 } as! Foo // Error, { b: number } is not assignable to Foo

const foo4 = { } as! Foo // Error, {} is not assignable to Foo
📃 Motivating Example

For example, such operator will allow to safely give named types to expressions without declaring extra variables or helper functions.

Consider an async function f that returns an object of type Foo:

type Foo = { a: number }

const f = async () => ({ a: 1 })

I want the returned object to strictly be of Foo type, how do I enforce this?

  1. Hard code the return type
const f = async (): Promise<Foo> => ({ a: 1 })

The problem here is that I must write Promise<Foo> instead of just Foo, but the Promise part can be inferred just fine. In real world these generics can be arbitrarily complex.

  1. Declare a variable
const f = async () => {
  const result: Foo = { a: 1 }

  return result
}

This is better than retyping generics but still pretty verbose.

  1. Use a helper function
const safeAssert = <T>(value: T): T => value

const f = async () => safeAssert<Foo>({ a: 1 })

This is ok but still requires writing/importing helper functions.

as is not an option here because it's unsafe, satisfies is neither because it doesn't name the type. Naming a type can be important for documentation purposes, this proposal allows to do this with less boilerplate.

const f = async () => ({ a: 1}) as! Foo // f: () => Promise<Foo>
💻 Use Cases

As described above, this feature can be used to safely cast expressions to specified types. A practical example when it can be useful is naming a type in an expression. Currently this is only covered by custom helper functions such as <T>(value: T): T => value.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

La issue propone una nuova sintassi as! e fornisce esempi di widening assertions, incluso il caso asincrono Foo. Non vengono indicati file sorgente, test o entry point del compilatore, quindi inizia individuando la gestione esistente di as e satisfies nel codebase TypeScript. Il lavoro è completo quando la sintassi impone la regola di assignability proposta, produce i tipi inferiti dichiarati e non modifica il JavaScript emesso.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.