Is it possible to determine the data type of a constant without having to widen

Is there a way to perform type checking on the value assigned to a variable without changing or widening its type?

For instance,

const a = {foo: "hi"} as const; // typeof = {foo: "hi"}

type THasFoo = {foo: string};
const b: THasFoo = {foo: "hi"} as const; // typeof = THasFoo

I want to verify that whatever is assigned to variable a contains the property foo, while still retaining the original type information.


Please note: I am specifically interested in the kind of verification achieved through direct assignment. For example,

const a = {foo: "hi", bar: "world"} as const;

type THasFoo = {foo: string};
const b: THasFoo = a;

This will pass. However,

type THasFoo = {foo: string};
const b: THasFoo = {foo: "hi", bar: "world"} as const;

Will not pass. I am looking for a similar form of validation (but without widening the type).

Answer №1

Disclaimer: While I may not have a black belt in TypeScript, my approach to this answer may not be the most optimal (or could even be worse).

const b = (<T extends THasFoo>(v: T) => v)(a);

This code snippet creates an anonymous function and immediately calls it. If a literal value is passed instead of variable a, it must adhere to the same rules of assignability (such as having identical properties) as if it were directly assigned.

A potential drawback is the introduction of an unnecessary function call, but modern engines may be able to optimize or eliminate it entirely.

Answer №2

Your method of implementation is not entirely clear to me, perhaps @zerkms's response aligns more closely with what you are seeking. However, my initial thought veered towards the concept of type guards. Essentially, we can create a function that validates if an object contains a property called foo which is of type string. If the function returns true, TypeScript will narrow down the specific type to include THasFoo without expanding any other types.

const hasFoo = <T extends {foo?: any}>(object: T): object is T & THasFoo => {
    return typeof object.foo === "string";
}

const a = {foo: "hello", bar: 42} as const;
if (hasFoo(a)) {
    console.log(a); // a will be refined to { readonly foo: "hello"; readonly bar: 42; } & THasFoo
}

const b = {foo: "hello", bar: 42};
if (hasFoo(b)) {
    console.log(b); // b will be refined to { foo: string; bar: number; } & THasFoo
}

Here is the Playground Link for demonstration.

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

Tips for displaying a specific amount of significant digits in a numerical output

Below is the JSON data that needs to be displayed on a web browser: { "testDoubleArr": [1, 2.0, 3.45], "testStr3": "SHA", "testDouble1": 12.56, "testDouble2": 1.0, "testStr1": "OMG" } When displayed on the browser, it appears in the following f ...

Navigating a Dynamic entity using a button in AFrame

I've inquired about this topic previously, but I feel my question wasn't clear. My goal is to construct a plinko-style aframe world with a ball that resets to its starting position when clicked. While I prefer to use a button to reset the ball, c ...

Can you clarify the distinction between store.destroy() and session.destroy()? Are both necessary to use?

I am currently working on incorporating/deleting sessions in my web application, and I'm a bit puzzled because it appears that there are two different ways to destroy sessions. Should I utilize both methods - store.destroy and session.destroy, or is j ...

Ways to have form inputs dynamically increase in value and then send the data via a post request

I've tried various methods to achieve the desired outcome but haven't had any luck. My goal is to have the innerHTML from the JavaScript below displayed a certain number of times, based on the dropdown selection, and then submit all fields to ano ...

How can you refresh a single element within an array using Angular.js?

System Background: The application is developed using Angular for the front end with routing capabilities, and Node.js, Express, MongoDB, and Mongoose for the back end. Within a controller, there is an array named $scope.array=[]; that is populated throug ...

Leveraging Vue.js as a development dependency in a TypeScript project

I am currently working on a .net core project where all client-side scripts are written in TypeScript. I have a desire to incorporate Vue.js into the TypeScript codebase. Below are snippets of the necessary configurations: tsconfig.json { "compilerOpti ...

Ways to modify menu when button is clicked?

I am currently working on creating an authentication-based menu in a React app. Menu Data: const menuItems = { primaryMenus: [ { title: 'Messages' }, { title: 'Register' }, { subMenus: { title: ...

Challenges arise when integrating PHP variables into JSON

I am facing an issue with the following JSON code: $dataB = <<<DATA { "actualArrivalDateTime":"2021-09-07T10:00", "containerNumber:" "000", "shipmentNumber": aaaa1, "co ...

The type 'Promise<any[]>' cannot be assigned to the specified type

Here is my unique interface: interface MeetingAttributeRecords { branches: Array<Promise<any>>; worshipStyles: Array<Promise<any>>; accessibilities: Array<Promise<any>>; } Below is a simplified version of my spec ...

Safely transmitting client-side encrypted information between individuals

I am developing a service that will keep personal information about a specific user, which should only be accessible by the author and the intended recipient. I want to encrypt the data on the client-side and store the encrypted version on the server. Res ...

Is it possible to predict the completion time of the initial build when using the "--watch" option for TypeScript compilation?

Simultaneously building Tokens and ModulesCollection can occur in parallel while the Lexer will build once Tokens and ModulesCollection are built for the first time. The following code snippet contains an error due to the use of & in the line npm run & ...

Error encountered in vue.js due to a ReferenceError when the resize event is used

I'm having trouble obtaining the window height when resizing, and I keep encountering the error ReferenceError: calcOfSliderHeight is not defined. Can someone explain what's happening? Here is my code: let example = new Vue({ el: '#exam ...

Adjust the map zoom and boundaries for all markers on Google API v3

I have been struggling with implementing latlngbounds to dynamically fit all the pins in the map canvas. If anyone has experience with a similar issue and can provide guidance on where my code might be going wrong, I would greatly appreciate it. var geo ...

How to Retrieve URL Before Closing a jQuery Window Using window.open()?

Is it feasible to retrieve the URL of a window.open window after triggering a window.close event when the user clicks the close button? How can I obtain the last URL visited right before the window closes? ...

Ways to update the DOM once a function has been executed in VUE 3 JS

I'm working on implementing a "like" or "add to favorite" feature in VUE 3. However, I'm facing an issue where the UI doesn't update when I like or unlike something. It only refreshes properly. I'm using backend functions for liking and ...

(IONIC) Issue with MomentJS locale functionality not functioning properly post-building process

I am currently utilizing the IONIC Framework and incorporating Moment.js for handling dates. I have set all strings to be in French using the code below: moment.locale('fr'); Interestingly, this works perfectly on the "serve" mode of Ionic. Ho ...

Tips for adjusting a duplicated row without altering the initial row

I've got a table row set up like this: <tr class="tr_clone"> <td> @part.PartIDLink </td> <td> @Html.DisplayFor(x => x.Parts[i].MFGNumber) @Html.HiddenFor(x => x.Part ...

cycle through several handlebars entities

Hey friends, I could really use your help right now. I'm attempting to iterate through these objects using handlebars. RowDataPacket { idUser: 1, username: 'xxxxxx', password: 'xxxxx', fullname: 'Julian Rincon'}, RowDat ...

After refreshing the compiler, the .toggleClass() method in React jQuery finally functions properly

I've been working on creating a sideboard for my react application and found this helpful example: https://codepen.io/illnino/pen/nwPBrQ. However, I've encountered an issue that I can't seem to solve on my own. What is the exact problem I&a ...

How to use puppeteer to extract images from HTML that have alt attributes

<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 nopadding text-center"><!-- Start Product Photo --><div class="row"><img src="/products/ca/downloads/images/54631.jpg" alt="Product image 1">&l ...