Issue with Typescript Conditional Type not being functional in a function parameter

For a specific use-case, I am looking to conditionally add a key to an interface. In attempting to achieve this, I used the following code:

key: a extends b ? keyValue : never

However, this approach breaks when a is generic and also necessitates explicit passing of 'never' as the value for the key.

The main questions here are how to make the generic aspect work and how to effectively "filter out" never types so that they don't have to be explicitly passed.

Typescript Playground with the above example

export type Component<T extends ComponentList> = {
    id: T;
    kids: GetProps<T> extends { children: Record<string, any> } ? string[] : never;
};


// Change Wrapper to Button and you will see that kidType changes between string[] and never like it is supposed to
// But as an argument to reComponent it always thinks that the kids option is never, and it also asks me to give it a never option ??
type WrapperProps = GetProps<"Wrapper">
type kidType = WrapperProps extends {children: Record<string, any> } ? string[] : never;   

const reComponent = <T extends ComponentList>(arg0: Record<string, Component<T>>) => {};

reComponent({
    button1: {id: "Button" },
    wrapper1: {id: "Wrapper", kids: [""]},
});


var Wrapper = ({
    children,
}: {
    children: Component<'Wrapper'> | Component<'Button'>
}) => {
    return "react.component"
};

var Button = ({
    text,
}: {
    text: string
}) => {
    return 123
};

var Components = {
    Wrapper,
    Button,
};


export type ComponentList =
    | 'Wrapper'
    | 'Button'

export type GetProps<T extends ComponentList> = Parameters<typeof Components[T]>[0];


Answer №1

When it comes to interfaces in TypeScript, the never type cannot be used to remove a key. An example of this is:

type testNever = {
    x : string;
    y : never;
}

var tn: testNever = { x: 'ab' }   // error: property 'y' is missing

The purpose of the never type is to indicate that a function will never return. More information can be found in the TypeScript Handbook, under the section 'More on functions'

If you want to make a key optional, you can use the question mark. To ensure a key is required, use the Required keyword. Here's an illustration:

type TypeWithOptionalY = {
    x : string;
    y? : string;
}

type TypeWithRequiredY = Required<TypeWithOptionalY>

type WithOrWithoutY = 'requiredY' | 'optionalY'

type ConditionalY<T extends WithOrWithoutY> =
    T extends 'requiredY'
        ? TypeWithRequiredY
        : TypeWithOptionalY

var objWithoutY : ConditionalY<'optionalY'> = { x: 'abc' }   
var objWithY : ConditionalY<'requiredY'> = { x: 'abc', y: 'def' }

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

What situations call for the use of 'import * as' in TypeScript?

Attempting to construct a cognitive framework for understanding the functionality of import * as Blah. Take, for instance: import * as StackTrace from 'stacktrace-js'; How does this operation function and in what scenarios should we utilize imp ...

Displaying object properties in React and rendering them on the user interface

Within my React application, I am retrieving data from an API using the following code snippet: function PlayerPage() { interface PlayerDataType { id: number; handle: string; role: string; avatar: string; specialAbilities: null; s ...

Function arity-based type guard

Consider a scenario where there is a function with multiple optional parameters. Why does the function's arity not have a type guard based on the arguments keyword and what are some solutions that do not require altering the implementation or resorti ...

Adding a fresh element to an array in Angular 4 using an observable

I am currently working on a page that showcases a list of locations, with the ability to click on each location and display the corresponding assets. Here is how I have structured the template: <li *ngFor="let location of locations" (click)="se ...

Connect an Observable to the template with async binding

I've been attempting to link an Observable to a template variable in Angular using the following code: [class.active]="isBookmarked$ | async" During the ngOnInit function, I initialize the Observable: var promise = this.cacheService.getItem(this.bo ...

Issue with setting value using setState in TypeScript - what's the problem?

Every time I attempt to update the value of currentRole, it appears highlighted in red. Here is a screenshot for reference: const Container: React.FC<ContainerProps> = ({ children }) => { const [role, setRole] = useState<string>(); useE ...

Does the value of an Angular reactive form control only reflect what the user inputs?

I am working with a reactive form where I need to extract values and assign them to a variable defined in an interface. The form is populated using the Google Places API, which disables user interaction with all controls except for the initial address inpu ...

Expanding the property of an established type to a nested type

Let's talk about titles. Well, maybe not this one. I tried to come up with a good title, but it didn't work out as planned. In my coding journey, I have created a cool interface called DefaultTheme: export interface DefaultTheme { colors: ...

Can anyone tell me the best way to access the name attribute of an HTML element in TypeScript?

Currently, my code is utilizing the name attribute to verify whether the user has entered information in a specific field and validating the input. However, I am facing an issue where the submit button remains active even if there are empty fields presen ...

Tips for retrieving the Solana unix_timestamp on the front-end using JavaScript

Solana Rust smart contracts have access to solana_program::clock::Clock::get()?.unix_timestamp which is seconds from epoch (midnight Jan 1st 1970 GMT) but has a significant drift from any real-world time-zone as a result of Solana's processing delays ...

The error message "NullInjectorError: No provider for HTTP!" is generated by the ionic-native/http module

Currently working with ionic 3.2 and angular. To install the HTTP module (https://ionicframework.com/docs/native/http/), I used the following commands: ionic cordova plugin add cordova-plugin-advanced-http npm install --save @ionic-native/http In my scri ...

The error at core.js:4002 is a NullInjectorError with a StaticInjectorError in AppModule when trying to inject FilterService into Table

While exploring PrimeNg Table control in my application - as a beginner in PrimeNg & Angular, I encountered an error No provider for FilterService! shown below: core.js:4002 ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppMo ...

What is the process for generating an index.d.ts file within a yarn package?

I'm facing an issue with creating the index.d.ts file for my yarn package. Here is my configuration in tsconfig.json: { "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"], " ...

Is it possible to modify the parameters of a function by utilizing a MethodDecorator without affecting the "this" value?

Consider a scenario where you need to dynamically modify method arguments using a decorator at runtime. To illustrate this concept, let's simplify it with an example: setting all arguments to "Hello World": export const SillyArguments = (): MethodDec ...

Error: The property 'children' is not found in type '{ children?: ReactNode; }'

I have been working on implementing the search bar feature from the provided link. Despite my efforts to match the types correctly, I keep encountering a TypeScript error. Homepage.tsx const [searchQuery, setSearchQuery] = useState(query || '' ...

The concept of a generic type serving as a characteristic of an incoming argument

What is the best way to assign a type property of an argument to a generic in TypeScript? Here's the code snippet: const foo = <T = someObject.bar>(someObject: {[string]: any}): T => { return someObject.bar } How can we set the type of ...

Resizing svg to accommodate a circle shape

As I work on my vue.js app that involves a plethora of diverse icons, I made the decision to create a small icons builder in node.js. The purpose is to standardize their usage and also "crop" each SVG so it fits perfectly within its parent container by uti ...

There is no initial value set for the property and it is not definitively assigned in the constructor

I encountered an issue while working on the following code snippet: export class UserComponent implements OnInit { user: User; constructor() { } ngOnInit() { this.user = { firstName : "test", lastName ...

Enhancing NG Style in Angular 6 using a custom function

Today, my curiosity lies in the NG Style with Angular 6. Specifically, I am seeking guidance on how to dynamically update [ngStyle] when utilizing a function to determine the value. To better illustrate my query, let me present a simplified scenario: I ha ...

Is there a way for me to use TypeScript to infer the type of the value returned by Map.get()?

type FuncType<O extends Object> = (option: O) => boolean export const funcMap: Map<string, Function> = new Map() const func1: FuncType<Object> = () => true const func2: FuncType<{prop: number}> = ({ prop }) => prop !== 0 ...