microsoft / microsoft/TypeScript
Safe type assertion (upcast / widening) operator
Nadie ha tomado este issue todavía.
- 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?
- 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.
- Declare a variable
const f = async () => {
const result: Foo = { a: 1 }
return result
}
This is better than retyping generics but still pretty verbose.
- 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
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- 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