Is there a specific type that is narrower in scope when based on a string parameter?

tgmlDoc.createElement(tagName) typically returns objects of type any. I am looking to refine the return type in the function below in order to simplify the rest of my code. Is there a way to accomplish this? My attempt is shown below, but unfortunately, the return type remains as TgmlTgml | TgmlLayer | null no matter what tagName is passed to the function. Ideally, I would like it to be TgmlTgml | null if tagName 'tgml' is passed and TgmlLayer | null if tagName 'layer' is passed.

export function createElementIfAllowed(tagName: string, parent: TgmlDocument | TgmlElement) {
  if (!allowedInParent(tagName, parent)) {
    return null;
  }
  const tgmlDoc = parent.ownerDocument || parent;
  const child = tgmlDoc.createElement(tagName);
  // Narrowing down the types from any
  if (child instanceof TgmlTgml) {
    return child;
  } else if (child instanceof TgmlLayer) {
    return child;
  } else {
    throw new Error(`TGML Element with tagname ${tagName} not allowed`);
  }
}

Answer №1

The solution to this problem involves utilizing function overloading, where each string value has a more specific signature.

It is not necessary to check instanceof, as it is acceptable to narrow any type to other types.

export function createElementIfAllowed(tagName: "Tgml", parent: TgmlDocument | TgmlElement): TgmlTgml | null;
export function createElementIfAllowed(tagName: "Layer", parent: TgmlDocument | TgmlElement): TgmlLayer | null;
export function createElementIfAllowed(tagName: string, parent: TgmlDocument | TgmlElement): TgmlElement | null {
  if (!allowedInParent(tagName, parent)) {
    return null;
  }
  const tgmlDoc = parent.ownerDocument || parent;
  const child = tgmlDoc.createElement(tagName);
  if (child instanceof TgmlTgml) {
    return child;
  } else if (child instanceof TgmlLayer) {
    return child;
  } else {
    throw new Error(`TGML Element with tagname ${tagName} not allowed`);
  }
}

function isTgmlDocument(val: any): val is TgmlDocument {
  return val instanceof TgmlDocument;
}

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

The conflicting definitions of identifiers in one file are at odds with those found in a

Currently, I am in the process of updating an aged component from Typescript version 6 to version 8. After making changes to the Jasmine dependencies listed in the package.json, a new error has been encountered: "There are conflicting definitions for th ...

Transforming a JSON file that has been previously converted to an Observable into a TypeScript map within an Angular application

There is a json data file named dummy, with the following structure: [ {"key":"KEY1", "value":["alpha","beta","gamma"]}, {"key":"KEY2", "value":["A","B","C"]}, {"key":"KEY3", "value":["One","Foo","Bar"]} ] The goal is to convert this json f ...

Angular 2 template can randomly display elements by shuffling the object of objects

I am working with a collection of objects that have the following structure: https://i.stack.imgur.com/ej63v.png To display all images in my template, I am using Object.keys Within the component: this.objectKeys = Object.keys; In the template: <ul ...

What is the most efficient method for examining dependencies in Yarn 2 (berry)?

Is there a way to check for vulnerabilities in Yarn 2 dependencies? In Yarn 1.x, you could run yarn audit, similar to npm audit. However, this command is not available in Yarn 2. According to this issue on the Yarn berry Github, it may not be implemented ( ...

Angular has a built-in function to determine the next ID after deletion of some items

I am currently facing a situation where I have a list of contacts in a detailed view and navigating through them using the following code: <nav> <a [routerLink]="['/details', friend.id - 1 ]" *ngIf="!(friend.id == 1)"> P ...

Having trouble injecting ActivatedRouteSnapshot into the component

Struggling to inject ActivatedRouteSnapshot into a component, encountering errors when trying to access query params. Here is the error stack trace: "Error: Can't resolve all parameters for ActivatedRouteSnapshot: (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). a ...

Despite using Enzyme to locate a component again, the expected prop value is still not being returned

Two components are involved here - a modal and a button that is meant to open the modal by setting its isOpen prop to true. The initial state of the modal is set to false, but when the button is clicked, it should change to true. While everything works fi ...

Using Angular 2, you can pass an object as a parameter to a function

Is there a way to pass an object as a parameter in the DOM on this forum? Within my HTML code, I have the following: <div class="list-items"> <ul> <li *ngFor="let i of item"> <span (click)="onAdd({{newUser.us ...

Ensure that the interface limits the key value to match precisely the value of a constant in Typescript

Seeking assistance in understanding how to enforce a specific type for an optional key within an interface: const FIRST = "FIRST" const SECOND = "SECOND" interface TSomeInterface { element: Element order?: typeof FIRST | typeof ...

Unable to bind to ngModel as it returned as "undefined" in Angular 8

Whenever I bind a property to ngModel, it consistently returns undefined <div> <input type="radio" name="input-alumni" id="input-alumni-2" value="true" [(ngModel) ...

Managing simultaneous asynchronous updates to the local state

There is a scenario where a series of asynchronous calls are made that read from a local state S, perform certain computations based on its current value, and return an updated value of the local state S'. All these operations occur at runtime, with ...

"Implementing a call and waiting at intervals by utilizing the subscribe function in Angular 6

In my code, I have a method that is called every 10000 times. Now, I want to modify this so that the function getAllNotificationsActed0() is invoked every 10 seconds. If the data does not arrive within this interval, I do not want the function to be called ...

When I select a checkbox in Angular 2, the checkall function does not continue to mark the selected checkbox

How can I check if a checkbox is already marked when the selectAll method is applied, and then continue marking it instead of toggling it? selectAll() { for (let i = 0; i < this.suppliersCheckbox.length; i++) { if (this.suppliersCheckbox[i].type == " ...

What seems to be the issue with my @typescript-eslint/member-ordering settings?

I am encountering an issue where my lint commands are failing right away with the error message shown below: Configuration for rule "@typescript-eslint/member-ordering" is throwing an error: The value ["signature","public-static-field","pro ...

What is the best way to add a repository in Nest.js using dependency injection?

I am encountering an issue while working with NestJS and TypeORM. I am trying to call the get user API, but I keep receiving the following error message: TypeError: this.userRepository.findByIsMember is not a function. It seems like this error is occurring ...

Classify the array types based on their indexes within the map

Is there a way to efficiently access elements in TypeScript using a map with the correct type? When attempting this, an error is thrown due to the type from the map being number | string type Tuple = [number, number, string]; const y: Tuple = [1, 2, &apos ...

Tips for adding an item to an array within a Map using functional programming in TypeScript/JavaScript

As I embark on my transition from object-oriented programming to functional programming in TypeScript, I am encountering challenges. I am trying to convert imperative TypeScript code into a more functional style, but I'm struggling with the following ...

The class constructor in the TSdx package must be invoked with the 'new' keyword

I recently developed a npm package using TSdx to create a small Jest reporter. However, when I try to use this package in another project, an error occurs. Uncaught TypeError: Class constructor BaseReporter cannot be invoked without 'new' at ...

Using Omit<T,K> with enums does not yield the expected result in Typescript

The setup includes an enum and interface as shown below: enum MyEnum { ALL, OTHER } interface Props { sources: Omit<MyEnum, MyEnum.ALL> } const test: Props = { sources: MyEnum.ALL } // triggering a complaint intentionally I am perplexed b ...

Designing a visual showcase with interactive tab links for image selection

I have been working on developing an Angular component that simulates a tab gallery functionality, inspired by this example. Below is my HTML structure: <div class="gallery-container"> <div class="display-container"> ...