What is the process by which TypeScript verifies validity when type assertions are made in TypeScript?

Currently, I am diving into the concept of type assertion in typescript. Despite going through various resources like the official documentation, an older version, and other articles such as this one, I still find myself puzzled about how typescript validates type assertions as valid.

To illustrate my confusion, consider the following example:

I have defined several types in my code:


type typA = {
    name: string;
};

type typB = {
    name: string;
    age: number;
};

type typC = {
    isGraduated: boolean;
};

type typD = {
    address: string;
    age: number;
};

type typEmpty = {};

Next, I have declared variables with the above-defined types:


let a: typA = {
    name: "John",
};

let b: typB = {
    name: "Alex",
    age: 10,
};

The issue arises when I execute the following code snippets:


a as typEmpty;           // (1) Ok
b as typEmpty;           // (2) Ok

a as typB;               // (3) Ok
b as typA;               // (4) Ok

b as typC;               // (5) error: ts(2352) Conversion of type '...' to type '...' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
b as typD;               // (6) error: ts(2352) Conversion of type '...' to type '...' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
1 as string              // (7) error: ts(2352) Conversion of type '...' to type '...' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

b as never as typC;      // (8)  suprisingly, Ok
b as unknown as typC;    // (9)  suprisingly, Ok
b as any as typC;        // (10) suprisingly, Ok
1 as never as string     // (11) suprisingly, Ok

I am left wondering why (8), (9), (10), and (11) are marked as Ok while (5), (6), and (7) throw errors. Any insights would be greatly appreciated!

I've done extensive research before posting this query here, but unfortunately, I haven't been able to find satisfactory explanations yet.

Thank you for mulling over my seemingly foolish question.

Answer №1

When Typescript attempts to implicitly convert a type into another, it is identified as unsafe and conversion is only allowed if explicitly stated. To address this issue, the error message recommends converting the values to unknown first, which highlights why (9) was deemed acceptable.

For more information, check out:

and: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html

In TypeScript 3.0, a new top type known as unknown is introduced. unknown serves as the type-safe equivalent of any. While anything can be assigned to unknown, unknown cannot be assigned to anything other than itself or any without a type assertion or narrowing based on control flow. Similarly, no operations are permitted on an unknown type without prior assertion or narrowing to a more specific type.

The excerpt above is directly quoted from the documentation. Given that anything can be assigned to unknown, it explains why (9) was considered valid and not unexpected.

For further details, refer to: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#any

❌ Avoid using any unless transitioning a JavaScript project to TypeScript. The compiler essentially treats any as “please turn off type checking for this thing”. It is akin to placing an @ts-ignore comment around every instance of the variable. While beneficial during initial migration from JavaScript to TypeScript, using any in a complete TypeScript project disables type checking for relevant program sections.

Hence, utilizing any deactivates type checking for the variable, making (10) permissible as well.

Per the documentation, things are not assignable to never:

https://i.sstatic.net/IeVpk3Wk.png

To learn more, visit: https://www.typescriptlang.org/docs/handbook/type-compatibility.html#any-unknown-object-void-undefined-null-and-never-assignability

Therefore, while (8) and (11) might appear surprising, in your scenario where types are transformed to never, it could potentially make sense.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What's the best way to streamline the code that sets up the list of validatees and validators in Angular's ReactiveFormsModule?

My form validation is currently based on ReactiveFormsModule, structured like this. Although I have multiple validators for each field, the process is quite repetitive. constructor(private builder: FormBuilder) { this.form = builder.group({ "firstNa ...

Can you pass two different data types into a template function in the C++ programming language?

I am attempting to find the absolute value of two numeric values provided by a user, while also allowing for different data types to be entered (such as an integer and a double, or a char and a float). I am considering using a function similar to this: te ...

Are there challenges and ways to handle errors with React Hook Form in Typescript?

Transitioning to React Hook Form from Formik while incorporating Material UI V5 and yup for validation poses a current challenge. There are two key issues I am addressing: Encountering TS Errors related to various RHF props and options. Desiring validati ...

The 'filter' property is not found on the type '{}'

I'm currently attempting to implement a custom filter for an autocomplete input text following the Angular Material guide. https://material.angular.io/components/autocomplete/overview Here's what I have so far: TS import { Component, OnInit } ...

Remove user from axios response interceptor for server-side component

In my Next.js 14 application, I have set up axios interceptors to handle errors. However, I need assistance in logging out the user and redirecting them to the '/login' page if any error occurs. Below is the code snippet for the interceptors: axi ...

In TypeScript, how can we specify that a key is mandatory for an object but it can be referred to by two different names?

Essentially, I'm faced with a situation where I need to handle a style object that must contain either the maxHeight or height properties. If one of these properties is included, the other becomes unnecessary. Despite my efforts, I have been unable to ...

Is it possible to dynamically assign class properties from an array in JavaScript/TypeScript?

Greetings for the assistance in advance. Currently, I am working with TypeScript, but I believe any JS solution will suffice. I aim to create something akin to the following: class ExcelData { 'Id 1': items[0].id, 'Quantity 1': item ...

Is Angular 11 Compatible with Internet Explorer 5?

Is there a way to make Angular 11 compatible with Internet Explorer 5? I am developing an angular solution for a client whose default browser is Internet Explorer running on version 5 (by default). Initially, I am not supposed to change any browser configu ...

Standing alone, an argument can never be fully validated without

Recently, while delving into the valuable resource titled Effective TypeScript by Dan Vanderkam, I stumbled across an intriguing scenario that left me puzzled. Within a code snippet presented in the book, there was a line - shape; that seemed perplexing ...

Expanding the capabilities of HTML anchor tag elements with React and TypeScript

In my React project using TypeScript, I am encountering an issue with accessing the properties of an link element compared to an a element. Whenever I try to use the properties of a link tag with an a tag, it results in an error. Is there a specific &apos ...

Problem with Typescript: The type '{ x;y }' is required to have a '[Symbol.iterator]()' method

Just starting out with Typescript and tackling the task of converting a React project from JavaScript to TypeScript. I've been diving into various posts for guidance, but I feel like I'm going in circles. Any assistance would be greatly appreci ...

Mastering the art of utilizing optionals in VueTS

As a relatively new coder, especially in Vue, I am curious about the best ways to declare non-existent values based on context using Vue / Typescript. Initial thoughts: It's important that variables bound to component templates are never undefined, ...

Interactive form control for location details including country, state, district, and town

I am struggling with adding dynamic form controls on dropdown change. I have been able to add them, but encountered an error preventing me from retrieving the value in 'formName.value'. The specific error message states: "Error: There is no Form ...

At what point is it appropriate for a class to incorporate an interface?

Currently working on a project and I've noticed developers using TypeScript in the following way: export class Ledger implements ILedger { LedgerID: number; CashAmmount: number; Units: number; ...

Unable to set value using React Hook Form for Material-UI Autocomplete is not functioning

Currently, I am in the process of constructing a form using React-Hook-Form paired with Material-UI. To ensure seamless integration, each Material-UI form component is encapsulated within a react-hook-form Controller component. One interesting feature I a ...

Unable to connect Formik Validation Errors to an array of objects

I am working on a form that consists of two fields: a boolean value and an array of objects. When the boolean value is true, the array becomes a required field. The array contains two string fields - one is required and the other is not. Validation Schema ...

Leverage the power of AWS SDK Amplify to securely retrieve a folder stored in an

Currently, I am utilizing amplify to retrieve a folder from S3. However, it seems that only a single file can be downloaded using this method, unlike the .NET SDK which offers the DownloadDirectoryAsync function. Does anyone know of a solution or workaroun ...

Unable to execute an Angular 2 application within Visual Studio 2015

I encountered an error while trying to set up an environment on VS 2015 with Angular2. Whenever I run the command "npm start," I receive the following error message. I attempted using "npm cache clean --force" before running "npm start," but the error pers ...

Is it possible to combine two enums in TypeScript to create a single object with key-value pairs?

Incorporating two enums named Key and Label, as well as an interface called IOption, the goal is to generate an array of objects known as IOptions. const enum Key { Flag = 'flag', Checkbox = 'checkbox', Star = 'star&apo ...

Creating a personalized connect function in Typescript for react-redux applications

Currently, I am in the process of migrating a large and intricate application to Typescript. One specific challenge we are facing is our reliance on createProvider and the storeKey option for linking our containers to the store. With over 100 containers in ...