Ways to indicate in Typescript that a value, if it exists, is not undefined

Is there a way to represent the following logic in TypeScript?

type LanguageName = "javascript" | "typescript" | "java" | "csharp"

type LanguageToWasmMap = {
  [key in LanguageName]: Exclude<LanguageName, key>
}

//I need this assignment to be successful
const languageNameToWasmNameMap: LanguageToWasmMap = {
  "javascript" : "typescript"
}

//I want this assignment to throw an error
const languageNameToWasmNameMapWithUndefined: LanguageToWasmMap = {
  "javascript" : undefined
} 

Try it out on Typescript playground : Click Here

Upon further consideration, it seems logical to make the LanguageToWasmMap optional and perform a runtime check for undefined values.

Answer №1

Utilize Partial in TypeScript to specify that not all keys are required.

    type LanguageName = "javascript" | "typescript" | "java" | "csharp"
    
    type LanguageToWasmMap = {
      [key in LanguageName]: Exclude<LanguageName, key>
    }
    
    //I want the below to not raise an error
    const languageNameToWasmNameMap: Partial<LanguageToWasmMap> = {
      "javascript" : "typescript"
    }
    
    //I want the below to raise an error
    const languageNameToWasmNameMapWithUndefined: LanguageToWasmMap = {
      "javascript" : undefined
    } 

playground

Answer №2

To ensure flexibility, you can make certain properties optional by setting exactOptionalPropertyTypes=true in tsconfig. This will prevent the use of underfined for optional fields.

type LanguageName = "javascript" | "typescript" | "java" | "csharp"

type LanguageToWasmMap = {
  [key in LanguageName]?: Exclude<LanguageName, key> | never
}

//I want the below to not throw error
const languageNameToWasmNameMap: LanguageToWasmMap = {
  "javascript": "typescript"
}

//I want the below to throw error
const languageNameToWasmNameMapWithUndefined: LanguageToWasmMap = {
  "javascript": undefined
} 

Playground

Answer №3

After implementing the as keyword, it appears to resolve the issue at hand. However, I am uncertain if this approach may introduce any unforeseen consequences.

type ProgrammingLanguage = "javascript" | "typescript" | "java" | "csharp"

type LanguageMapping = {
  [key in ProgrammingLanguage]: Exclude<ProgrammingLanguage, key>
}

// The following should not generate an error
const languageMap = {
  "javascript": "typescript"
} as LanguageMapping

// The following should trigger an error
const languageMapWithUndefined = {
  "javascript": undefined
} as LanguageMapping

Interactive Playground

Answer №4

Perhaps a solution could involve making the type generic, although it would require specifying the key twice:

    type LanguageName = "javascript" | "typescript" | "java" | "csharp"
    
    type LanguageToWasmMap<K extends LanguageName = LanguageName> = {
      [key in K]: Exclude<LanguageName, key>
    }
    
    // The intention is for the code below not to throw an error
    const languageNameToWasmNameMap: LanguageToWasmMap<"javascript"> = {
      "javascript" : "typescript"
    }
    
    // The goal here is for the code below to throw an error
    const languageNameToWasmNameMapWithUndefined: LanguageToWasmMap = {
      "javascript" : undefined
    } 

Play

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

Pipe for Angular that allows for searching full sentences regardless of the order of the words

I am looking to create a search bar that can search for the 'title' from the table below, regardless of the word order in the sentence. I attempted to use a filter pipe to check if the search string exists in the title. I also experimented with ...

Tips for selecting objects based on property in Typescript?

Consider this scenario: import { Action, AnyAction } from 'redux'; // interface Action<Type> { type: Type } and type AnyAction = Action<any> export type FilterActionByType< A extends AnyAction, ActionType extends string > ...

What are the best practices for utilizing an array of routes?

I'm new to working with react but I noticed something strange. My routes are currently set up like this: <Main> <Route exact path="/home" component={Home} /> <Route exact path="/home1" com ...

Is it possible to verify if the @Output is correctly wired up within an Angular component?

When working with Angular and TypeScript, it is possible to access the bound @Input values in the ngOnInit method of a component. However, there isn't a straightforward way to check if a particular @Output event binding has been set up on the componen ...

Can a type alias be created for more than one parameter of a class or function with multiple type parameters?

When using Vue, there are situations where a generic function may require 3, 4, or even 5 type parameters. Is it possible to create a type alias for these parameters in order to avoid typing them out repeatedly? Something like this perhaps: // Example of ...

Issue: "The argument provided must be a specific string, not a string or an array of strings."

Currently, I am tackling a Vue project that incorporates TypeScript and axios for handling API requests. While working on the Reset Password component, the resetPassword function within the auth.ts file appears as follows: resetPassword(password1: string, ...

Refresh the information in the <ion-datetime> component by utilizing the formGroup

I am currently working with a form that has been created using 'FormBuilder'. The form includes a date control and I am trying to figure out how to update the data in that control using the patchValue() method. In the template, the control has d ...

Utilizing import for Ionic3 to export const with logic

While developing an app using ionic3, I encountered an issue with setting up a proxy. When running in a browser, Ionic was able to recognize the path of my proxyUrl as shown below. ionic.config.json { "name": "myApp", "app_id": "", "v2": true, "t ...

Refresh a page automatically upon pressing the back button in Angular

I am currently working on an Angular 8 application with over 100 pages (components) that is specifically designed for the Chrome browser. However, I have encountered an issue where the CSS randomly gets distorted when I click the browser's back button ...

Leveraging NPM workspaces in combination with Expo and Typescript

I'm struggling to incorporate NPM 7 workspaces into a Typescript Expo project. The goal is to maintain the standard Expo structure, with the root App.tsx file, while segregating certain code sections into workspaces. I'm facing challenges compil ...

Typescript: Removing signatures with a filter

I am encountering a TypeScript error stating that .filter has no signatures. I'm unsure of how to resolve this issue. interface IDevice { deviceId: string; deviceName?: string; } const joinRoom = ({ userId, deviceId, deviceName }: IRoomParams ...

Error: The identifier HTMLVideoElement has not been declared

Encountering an issue while attempting to build my Angular 9 Universal project for SSR: /Users/my-project/dist/server.js:28676 Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:type", HTMLVideoElement) ReferenceError: HTMLVideoElem ...

Enforcing object keys in Typescript based on object values

I'm looking to design a structure where the keys of an object are based on values from other parts of the object. For example: type AreaChartData = { xAxis: string; yAxis: string; data: { [Key in AreaChartData['xAxis'] | AreaChart ...

Swap out the default URL in components with the global constant

Could anyone offer some assistance with this task I have at hand: Let's imagine we have a global constant 'env' that I need to use to replace template URLs in components during build time. Each component has a default template URL, but for ...

Exploring Objects with Union Types in TypeScript

Looking to iterate through an object that combines two interfaces. interface Family { cat: string; age: string; family: string; lastYearFamily: string; } interface Model { cat: string; age: string; ...

Tips for updating ion-select option to correspond with the object by utilizing the object's identifier as the value

In my code, I have a select element that looks like this. <ion-select formControlName="location" (click)="clearSectionAndTask()"> <ion-select-option *ngFor="let location of locations" value="{{location.locationId}}"> ...

Retrieve class attributes within callback function

I have integrated the plugin from https://github.com/blinkmobile/cordova-plugin-sketch into my Ionic 3 project. One remaining crucial task is to extract the result from the callback functions so that I can continue working with it. Below is a snippet of ...

What is the best way to limit a property and template literal variable to identical values?

Instead of giving a title, I find it easier to demonstrate what I need: type Foo = "bar" | "baz"; interface Consistency { foo: Foo; fooTemplate: `${Foo} in a template`; } // This should compile (and it does) const valid1: Cons ...

Using the Vue.js Compositions API to handle multiple API requests with a promise when the component is mounted

I have a task that requires me to make requests to 4 different places in the onmounted function using the composition api. I want to send these requests simultaneously with promises for better performance. Can anyone guide me on how to achieve this effic ...

Backend communication functions seamlessly within the service scope, yet encounters obstacles beyond the service boundaries

I'm facing an issue with accessing data from my backend. Although the service successfully retrieves and logs the data, when I try to use that service in a different module, it either shows "undefined" or "Observable". Does anyone have any suggestions ...