microsoft / microsoft/TypeScript

Safe type assertion (upcast / widening) operator

Abierto
#56,235 11 comentarios 13 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Awaiting More Feedback Suggestion
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

🔍 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.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

El issue propone una nueva sintaxis as! y proporciona ejemplos de widening assertions, incluido el caso asíncrono Foo. No se nombran archivos fuente, pruebas ni puntos de entrada del compilador, así que empieza localizando el manejo existente de as y satisfies en el código base de TypeScript. Se considera terminado cuando la sintaxis impone la regla de assignability propuesta, produce los tipos inferidos indicados y no altera el JavaScript emitido.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
compilers
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Tranquilo
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.