Making decisions about data types during compilation?

Given an instance of type A or B, I want to implement a unified function that accepts a parameter of type A or B and returns its wrapped argument. Here is an example:

type A = { name: string };
type B = A[];

type DucktypedA = { // we don't care about the structure of this type as we can differentiate between A and B
  a: A,
};

type DucktypedB = {
  b: B,
}

function test(arg: A | B): DucktypedA | DucktypedB {
  if (arg instanceof A) {
    return { a: arg };
  } else {
    return { b: arg };
  }
}

My question is, can this be achieved in TypeScript?

const a = { name: "me" };
const wrappedA = test(a); // --> { a: { name: "me" } }

const b = [{ name: "me" }];
const wrappedB = test(b); // --> { b: [{ name: "me" }] }

Answer №1

Using the <code>instanceof operator with TypeScript types is not supported. However, it can be used with classes.

class Animal {}

const animal = new Animal();

console.assert(animal instanceof Animal)

To enforce type checking at runtime, you can create a type guard function. Play

function isAnimal(v: any): v is Animal {
    return 'name' in v
}

function checkType(arg: Animal | Bird): DucktypedAnimal | DucktypedBird {
  if (isAnimal(arg)) {
    return { a: arg };
  } else {
    return { b: arg };
  }
}

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

How can you define the types of function arguments when destructuring arguments in TypeScript?

TS throws an error that states: Error:(8, 20) TS7031: Binding element 'on' implicitly has an 'any' type. Error:(8, 24) TS7031: Binding element 'children' implicitly has an 'any' type. Below is the function I am wor ...

How to associate an object with a component in Angular2/TypeScript using HTTP

I am currently working on displaying a list of item names retrieved from a REST API. By utilizing the map function on the response observable and subscribing to it, I was able to obtain the parsed items object. Now, my challenge is how to bind this object ...

Retrieve the desired destination URL in the CanActivate guard when lazily loading modules in Angular

I am facing an issue with retrieving the target URL in the canActivate guard. Even though I have set up preloadingStrategy: PreloadAllModules in RouterModule.forRoot, the url property of ActivatedRoute does not contain the path. Here are the contents of bo ...

I encounter an error message stating "Cannot read property 'push' of undefined" when trying to add an item to a property within an interface

I have a model defined like this : export interface AddAlbumeModel { name: string; gener: string; signer: string; albumeProfile:any; albumPoster:any; tracks:TrackMode[]; } export interface TrackMode { trackNumber: number; ...

Designing a platform for dynamic components in react-native - the ultimate wrapper for all elements

export interface IWEProps { accessibilityLabel: string; onPress?: ((status: string | undefined) => void) | undefined; localePrefix: string; children: JSX.Element[]; style: IWEStyle; type?: string; } class WrappingElement extends React.Pure ...

What is the best way to automatically refresh an observable every 30 seconds?

@Component({ selector: 'app-geo', templateUrl: <img mat-card-image [src]="profileUrl | async "> export class GeoComponent implements OnInit { date; profileUrl: Observable<string>; constructor(private tempService ...

Vue.js 3 with TypeScript is throwing an error: "Module 'xxxxxx' cannot be located, or its corresponding type declarations are missing."

I developed a pagination plugin using Vue JS 2, but encountered an error when trying to integrate it into a project that uses Vue 3 with TypeScript. The error message displayed is 'Cannot find module 'l-pagination' or its corresponding type ...

Steps for updating the value of a button in Typescript and React

I currently have a button that manages my language switcher, configured to handle cookies, URL changes, and now I want it to update the translations on the page as well. The <img> tag is utilized for changing the country flag. < ...

Generating data types based on the output of functions

I'm currently working on optimizing my typescript react code by reducing repetition. I'm curious to know if there's a way to generate a type based on the return type of a known function? For example: const mapStateToProps = (state: StoreSt ...

Looking to organize an array of objects containing two string elements (countries) based on the country name using TypeScript or the Lodash library?

Below is an example of an array of objects I am working with: { countries: [{ "country_alpha2_code": "PW", "country_name": "PALAU" },{ "country_alpha2_code": "US&qu ...

Converting a JavaScript function to work in TypeScript: a step-by-step guide

When writing it like this, using the this keyword is not possible. LoadDrawing(drawing_name) { this.glg.LoadWidgetFromURL(drawing_name, null, this.LoadCB,drawing_name); } LoadCB(drawing, drawing_name) { if (drawing == null) { return; ...

I am sorry, but there seems to be an issue with the JSON input as it is ending

Whenever I try to submit the form in edit mode, I encounter two errors. An unexpected end of JSON occurred Input provided caused an unexpected end of JSON The update process works perfectly fine and successfully saves values in the database. However, I ...

Change the property value prior to running TypeScript validation

I possess the following object: const translations = { msg_hello: 'Hello', msg_bye: 'Bye' } In addition, I have a function that is structured as such: const generateTranslation = (partialKey: string): keyof typeof translations ...

I am encountering an issue in Vue3 where the parent event handler arguments are not being typed with the child's defineEmits definition. Can anyone explain this to me

I am struggling to correctly type the parent event handler based on the child definition, but no matter what I try, I always end up with `any` as the event type. Here is a code example: <script setup lang="ts"> // Child component type Even ...

In Angular 5, when you reset a required form control in a reactive form, the required error message beneath the input field is not cleared

Within my template, there is a form that becomes visible when a button is clicked- <form [formGroup]="person" (ngSubmit)="onSubmitNewPerson()" #formDirective="ngForm"> <mat-form-field> < ...

Excluding a common attribute from a combined type of objects can lead to issues when accessing non-common attributes (TypeScript)

In the process of developing a wrapper function, I am passing a refs property into a send function. The Event type used to construct my state machine is defined as an intersection between a base interface { refs: NodeRefs } and a union of possible event ob ...

Array containing multiple service providers in Angular

I encountered a problem while utilizing multiple providers in my application: ERROR Error: No provider for Array! at injectionError (VM634 core.umd.js:1238) [angular] at noProviderError (VM634 core.umd.js:1276) [angular] at ReflectiveInjector_._throwOrNul ...

Dropdown Pattern with React CTA Modal

While using MaterialUI's ButtonGroup for a dropdown menu, I encountered an issue trying to set up a series of CTAs that are easily interchangeable within it. The goal is to have all components reusable and the choices in the dropdown dynamic. const C ...

Automate the process of triggering the "Organize Imports" command on a VSCode / Typescript project through code

Is there a way to automatically run VSCode's 'Organize Imports' quickfix on every file in a project, similar to how tslint can be run programatically over the entire project? tslint --project tsconfig.json --config tslint.json --fix I want ...

Leveraging the find method to sort through an array with dual parameters

I'm facing an issue while trying to filter my array of objects using two parameters. Despite having an object in the array with the same values as the parameters, the result is empty. const item = this.lista.find(i => i.number === rule.number && ...