tips for utilizing a variable for inferring an object in typescript

In my current code, I have the following working implementation:

type ParamType = { a: string, b: string } | { c: string }

if ('a' in params) {
  doSomethingA(params)
} else {
  doSomethingC(params)
}

The functions doSomethingA and doSomethingC each accept specific parameter types.

The issue arises when I modified a key within { a: string, b: string }, TypeScript did not raise an error on 'a' in params as expected. To address this, I made the following adjustments:

type A = { a: string, d: string }
type B = { c: string }
type ParamType = A | B

const testKey: keyof A = 'd'

if (testKey in params) {
  doSomethingA(params)
} else {
  doSomethingC(params)
}

However, now TypeScript does not correctly infer the type of params inside the if/else statement, resulting in:

Property 'd' is missing in type 'B' but required in type 'A'.

Is there a way to ensure that the key used in the if statement comes from type A while maintaining correct types within the if statement itself?

Answer №1

It seems like TypeScript may not currently support this feature. While using if ('d' in params) { helps narrow down types in if branches, even using

const testKey = 'd'; if (testKey in params) {
does not work, despite the fact that testKey is identical to 'd' in that scenario.

To address this limitation, you can develop a custom type guard function that verifies keys. However, you must manually define and repeat the keys within the implementation since types do not carry over into runtime code.

type A = { a: string, d: string }
type B = { c: string }
type ParamType = A | B

function isA(ob:A|B, key:keyof A | keyof B): ob is A {
    return new Set(['a', 'd']).has(key);
}

const g = (params:ParamType) =>  {
    const testKey:keyof A = 'a'

    if (isA(params, testKey)) {
        doSomethingD(params)
    } else {
        doSomethingC(params)
    }
}

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

Compiler unable to determine Generic type if not explicitly specified

Here is a simple code snippet that I am working with: class Model { prop1: number; } class A<TModel> { constructor(p: (model: TModel) => any) {} bar = (): A<TModel> => { return this; } } function foo<T>(p: ...

Exploring the representation of recursive types using generic type constraints

Is there a way to create a structure that can handle recursive relationships like the one described below? I am looking to limit the types of values that can be added to a general container to either primitive data types or other containers. Due to limit ...

Obtain the data from onTouchTap action

Currently, I have a class that is returning an event to the parent. My goal is to extract the number of the touched button (the label on RaisedButton). Although I am successfully returning the event, I am unable to locate the desired information when I l ...

Unable to add data to an Array once subscribed to BehaviorSubject

Hello everyone, this is my first time asking a question here. I hope it's clear enough for you to understand :) Let's dive straight into the issue at hand. I have a query regarding a behaviorSubject variable in TypeScript that is not allowing me ...

Ways to display two tabs in reactjs

My typical app is running smoothly, but I am trying to implement a feature where it launches two tabs upon opening. The first tab should open with a normal path of '/' and the second one with a path of '/board'. Here's an example: ...

Is it possible to verify type equality in Typescript?

If the types do not match, I want to receive an error. Here is an example of an object: const ACTIVITY_ATTRIBUTES = { onsite: { id: "applied", .... }, online: { id: "applied_online", .... }, ... } as co ...

TypeScript: a sequence of symbols representing a particular <type>

Perhaps I'm going crazy. I have a roster of potential nucleotides and a corresponding type: const DNA = ['G', 'C', 'T', 'A'] as const; type DNA = typeof DNA[number]; So, a DNA strand could be a sequence of an ...

How can we strengthen the type checking when defining the sorting function for json properties?

When dealing with a json structure from a service that contains .attributes json values, I often find myself needing to sort either by id from the DTO or by several attributes from the IContactsAttributes. The microservice returns this specific structure: ...

Angular 5: experiencing issues with HttpClient when using REST API

Currently, I am in the process of developing a REST API using Spring to perform CRUD operations based on a tutorial I found. However, I have encountered an issue with the HTTP client not retrieving data, and upon inspection, I discovered the following erro ...

Integrate a service component into another service component by utilizing module exports

After diving into the nestjs docs and exploring hierarchical injection, I found myself struggling to properly implement it within my project. Currently, I have two crucial modules at play. AuthModule is responsible for importing the UserModule, which conta ...

Nuxt 3 turns a blind eye to TypeScript errors upon code saving

I am facing an issue. Even with a TypeScript error in the code, the IDE shows an error, but I am still able to save it and run it in the browser. Is this acceptable? Check out the code below: <script lang="ts" setup> const a = ref<strin ...

Can you explain the variance between the (Record<string, unknown>) and object type?

Can you explain the distinction between type Record<string, unkown> and type object? Create a generic DeepReadonly<T> which ensures that every parameter of an object - and its nested objects recursively - is readonly. Here's the type I c ...

Error in TypeScript: The property 'data' is not found within type '{ children?: ReactNode; }'. (ts2339)

Question I am currently working on a project using BlitzJS. While fetching some data, I encountered a Typescript issue that says: Property 'data' does not exist on type '{ children?: ReactNode; }'.ts(2339) import { BlitzPage } from &q ...

Error with object props in React using Typescript

Here's a scenario; I have a list of 'Reviews' that I am trying to render. The Proptype for these reviews is as follows: export interface Props { title: string; name: string; reviewdesc: string; rating: number; } In the pare ...

What is the best way to connect Classes and Objects in Angular5?

Picture a study tool with flashcards and different categories. Each category has a title, while each card contains content, is linked to only one category, and is also connected to another card. How can I establish these connections in Angular 5 and Types ...

Tips for displaying a multi-select dropdown in the Creative Tim Angular Material Pro filter panel

I am in need of assistance with modifying the standard Creative Tim Angular Pro Material template due to my limited CSS/SCSS skills. Could someone provide examples of the necessary changes, whether it involves altering the HTML or multiple CSS files withi ...

Creating Instances of Variables Within a Class

Currently, I am working on a project using Ionic and Angular. I have come across various ways of instantiating variables and I'm unsure about the implications of each method. Here are three scenarios that confuse me: export class someClass { myVaria ...

Troubleshooting TypeError: Not a Function in Typescript Mocha Testing

Currently, this is the class I am working with: import * as winston from 'winston'; const {combine, timestamp, printf, label, json} = winston.format; import {isEmpty, isNil} from 'lodash'; import {Log} from './Log'; export cl ...

Create a line break in the React Mui DataGrid to ensure that when the text inside a row reaches its maximum

I'm facing an issue with a table created using MUI DataGrid. When user input is too long, the text gets truncated with "..." at the end. My goal is to have the text break into multiple lines within the column, similar to this example: https://i.sstati ...

JSON TypeScript compliant interface

My problem is quite common, but the solutions found on stackoverflow are not suitable for my specific case. I have a collection of objects that I need to manipulate, save, and load as json files. Here's an example of the interface: type jsonValue = s ...