What is the purpose of using the `is` keyword in typescript?

Recently, I stumbled upon this code snippet:

export function foo(arg: string): arg is MyType {
    return ...
}

Despite searching through documentation and Google, I couldn't find information on the is keyword. It's a widely used word that appears almost everywhere.

Can someone please explain what the keyword does in this specific context?

Answer №1

To gain further insights, consult the documentation on user-defined type guard functions.

function determineString(input: any): input is string{
    return typeof input === "string";
}

function demonstrateExample(value: any){
    if(determineString(value)){
        console.log("This is a string: " + value);
        console.log(value.length); // string function
    }
}
demonstrateExample("hello world");

In the scenario depicted above, utilizing the type predicate input is string (rather than just returning

boolean</code), subsequent to calling <code>determineString()
, if the outcome is true, TypeScript will narrow down the type to string within any section safeguarded by invoking the function. The compiler will infer that value pertains to string in the enclosed guarded block (solely within the surrounded guarded block)

{
    console.log("This is a string: " + value);
    console.log(value.length); // string function
}

A type predicate is strictly used during compilation phase. The resultant .js file (during runtime) will exhibit no variance since it doesn't contemplate the TYPE.

The distinctions between the following four instances will be illustrated.

For instance 1: the provided code example won't trigger either a compile or runtime error.

For instance 2: the subsequent code snippet will generate a compilation error (as well as a runtime error) because TypeScript has narrowed down the type to string and verified that toExponential isn't contained within string method.

function demonstrateExample(value: any){
    if(determineString(value)){
        console.log("This is a string: " + value);
        console.log(value.length);
        console.log(value.toExponential(2));
    }
}

For instance 3: the ensuing code excerpt won't trigger a compile error but will encounter a runtime error as TypeScript solely narrows down the type to string in the guarded block, not post-guard, therefore, value.toExponential won't yield a compile error (TypeScript doesn't recognize it as a string type). However, during runtime, string lacks the toExponential method, hence leading to a runtime error.

function demonstrateExample(value: any){
    if(determineString(value)){
        console.log("This is a string: " + value);
        console.log(value.length);
    }
    console.log(value.toExponential(2));
}

For instance 4: if we exclude input is string (type predicate), TypeScript won't narrow down the type in the guarded block, and the following code snippet won't raise a compile error but it will incur a runtime error.

function determineString(input: any): boolean{
    return typeof input === "string";
}
function demonstrateExample(value: any){
    if(determineString(value)){
        console.log("This is a string: " + value);
        console.log(value.length);
        console.log(value.toExponential(2));
    }
}

Hence, employing input is string (type predicate) aids developers foresee potential runtime errors during compile time. With JavaScript, developers are unaware of these errors during compilation. This constitutes the advantage of leveraging TypeScript.

Answer №2

The primary purpose I am aware of is illustrated in your example: defining a "type predicate" (arg is MyType) within a user-defined Type Guard.

To learn more about User Defined Type Guards, check out this resource

For additional information, refer to this source

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

Troubleshooting a database update issue within an Angular and NestJS application

Hey there, I am a newcomer to both Angular and NestJS. I'm currently facing an issue with updating a specific row in my database through the frontend. While I can easily insert new data, updating seems to be problematic. Here's how my files are s ...

Patience is key as you wait for the observable to finish

My methods have dependencies where one method needs to complete before the next can be called. process1(data: string) : Observable<string> { this.dataservice.process(data).subscribe( (response) => { return response. ...

Encountering issues with retrieving application setting variables from Azure App Service in a ReactJS TypeScript application resulting in '

My dilemma lies in my app setup which involves a Node.js runtime stack serving a ReactJs Typescript application. I have set some API URLs in the application settings, and attempted to access them in ReactJs components using process.env.REACT_APP_URL, only ...

Merging an unspecified number of observables in Rxjs

My latest project involves creating a custom loader for @ngx-translate. The loader is designed to fetch multiple JSON translation files from a specific directory based on the chosen language. Currently, I am implementing file loading through an index.json ...

Prevent Angular from automatically scrolling to the top when subscribing to a timer

I have a real-time updating list of orders that is scrollable. This is the main component, where the list gets updated every 2 minutes with the following setup: ngOnInit(): void { this.internalError = false; this.subscription = timer(0, 120 * 1000) ...

Ways to stop dialog from disappearing in Reactjs

This code snippet demonstrates the implementation of a popup with buttons, where clicking the cancel button triggers a confirmation dialog. To make the popup disappear when clicked outside of it, the following event handling is employed: const popupRef = ...

The specified type '{ rippleColor: any; }' cannot be assigned to type 'ColorValue | null | undefined'

I've been diving into learning reactnative (expo) with typescript, but I've hit a roadblock. TypeScript keeps showing me the error message Type '{ rippleColor: any; }' is not assignable to type 'ColorValue | null | undefined' ...

There are zero assumptions to be made in Spec - Jasmine analyzing the callback function

I've encountered a challenge with a method that is triggered by a d3 timer. Each time the method runs, it emits an object containing several values. One of these values is meant to increase gradually over time. My goal is to create a test to verify wh ...

Implementing Batch File Uploads using Typescript

Is there a way to upload multiple files in TypeScript without using React or Angular, but by utilizing an interface and getter and setter in a class? So far I have this for single file upload: <input name="myfile" type="file" multi ...

How can I convert a property to an interface in Typescript?

I'm having trouble casting geometryType as I keep getting this error : IShape is a Type not a Namespace when attempting to do the following: interface IShape { readonly geometryType: "RECTANGLE" | "SQUARE" } let geom ...

Converting a nested JSON object into a specific structure using TypeScript

In the process of developing a React app with TypeScript, I encountered a challenging task involving formatting a complex nested JSON object into a specific structure. const data = { "aaa": { "aa": { "xxx&qu ...

In order to use the serve command, it is necessary to run it within an Angular project. However, if a project definition cannot be located

An error occurred while running the ng serve command: C:\Mysystem\Programs\myfwms>ng serve The serve command needs to be executed within an Angular project, but a project definition could not be found. I encounter this error when ...

What is the method for retrieving a child element from a TemplateRef variable?

I'm currently working with a component that has a modal feature. The modal is enclosed within an <ng-template> element. <ng-template #modalm let-modal> ... <button type="button" (click)="onSubmit()" class="bt ...

Issue with React Redux: Store dispatch not causing component update

I have recently implemented React Redux in my project, but I seem to be encountering some issues. Despite changing the state, the value remains the same. I attempted to use useStore(), but it does not take any parameters. Can anyone provide insight into wh ...

Create an array of arrays within a loop using TypeScript

My application contains an object with dates and corresponding time arrays. The console log output is displayed below: 32: { 1514160000: Array [ 1200, 1500 ], 1514764800: Array [ 1200, 1500 ], 1515369600: Array [ 1200, 1500 ], 1515974400: Array [ 700, 12 ...

Managing the browser's "back" button functionality in React

I am currently using "react-dom-router v6.3.0" (strictly!) and I am struggling to figure out how to manage the browser's "back" button functionality. Specifically, I want to be able to detect when the user clicks the back button so that I can display ...

What is the method to retrieve the total number of days in a moment-jalaali using NodeJS?

I'm trying to determine the number of days in the moment-jalaali package for NodeJS. Despite checking their API on GitHub, I couldn't find any reference to a specific method like numOfDay. ...

Angular: rendering JSON data as a dynamic grid

I'm looking to organize and display user scores by date in a matrix format where each user has only one score per date. My desired matrix layout is as follows: Date User1 User2 User3 2020-01-05 40 20 20 2020-01-03 40 ...

Examine every character in the text to determine if it qualifies as a separator

Can anyone assist me with a task I'm working on? I'm trying to write a function that checks the letters of a string. I attempted to use both a for loop and a foreach loop, but I couldn't get it to work properly :( let input = this.tagsFor ...

AWS Amplify is failing to maintain the user session post a successful login

Currently, I am developing an aws-serverless application using React. My main issue lies in the authentication process with aws-amplify. The authentication works smoothly, but the session is not being preserved. During the signing-in stage: await Auth.s ...