Búsqueda de sitios web

typescript - Aserción de tipo vs propiedades


He notado el siguiente comportamiento:

interface User {
    name: string;
    age: number;
}

let user:User = {
    name: "Aaron",
    age: 99
}

Si omito age: 99 obtengo un error de compilación. Este es el comportamiento que espero.

Sin embargo:

function putUser(user:User):void { }

putUser(<User> {
    name: "Aaron"
});

No obtengo un error de compilación por la propiedad no opcional age que falta.

De hecho, en mi base de código real he descubierto que con casting la aserción de tipo a veces puedo añadir propiedades completamente incorrectas al literal de objeto, pero no pude reproducir este comportamiento en un caso simple como el anterior.

¿Alguien puede explicar qué está pasando aquí?

Editar: Omitir la afirmación funciona, gracias @Amid. Sin embargo, donde me encontré con esto como un problema fue en este tipo de escenario:

interface User { name: string; }

function putUser(user:User):void { }

interface Musician extends User { instrument: string; }

putUser(<Musician> {
    name: "Bob Dylan"
});

El problema es que quiero validar el objeto Musician, pero putUser solo espera el objeto base User. Pensé que la aserción de tipo me daría mejor seguridad de tipo, pero en este caso en realidad reduce la seguridad de tipo.

Editar #2

Parece que puedo obtener lo que quería usando una restricción de tipo genérico, que en realidad se parece mucho a mi aserción de tipo:

function putUser<T extends User>(user:T):void { }

putUser<Musician>({
    name: "Bob Dylan",
    instrument: "Guitar"
});

En este caso parece que se asegurará de que el literal de objeto sea exactamente una implementación de Musician.

Respuesta #1

La razón es que estás usando una afirmación de tipo aquí. Básicamente, eso anula todas las comprobaciones de tipo de TypeScript. Si quitas la parte < User >, el compilador te dará el error que esperas

EDITAR :

Esto es lo que quieres:

interface User { name: string; }

function putUser<T extends User>(user:T):void { }

interface Musician extends User { instrument: string; }

putUser<Musician>({
    name: "Bob Dylan"
});

Respuesta #2

Hiciste una aserción de tipo. Preferirías usar aserciones de tipo cuando te comuniques con sistemas externos (como al solicitar una API) cuando tienes la forma de los datos que vas a recibir pero no tienes una fuente propia de ellos.

Las aserciones de tipo en TypeScript son bastante inteligentes. No te permitirán hacer cosas completamente incorrectas. Aquí hay un ejemplo:

interface Point {
    x: number;
    y: number;
}

function process(box: Point) {}

let empty = {};
let part = { x: 3 };
let full = { x: 3, y: 5 };
let vague = { x: 3, y: 5, z: 7 };

process(empty); //type mismatch, got {} expected {x, y} 
process(part); //type mismatch, only {x} expected {x, y}
process(null); //no type mismatch, argument can be null
process(full); //full match
process(vague); //still works, but the function is not aware of "z" field.

process(<Point>empty); //assertion valid, object can be a Point instance
process(<Point>"123"); //wrong assertion, expected object instead of string
process(<Point>[]); //wrong assertion, expected object instead of array