Function Type Alias with No Particular Name

Have you ever wondered why in TypeScript type alias doesn't work with a generic function? Take for example the scenario where TS fails to define type Identical as generic.

type Identical = <T>(v: T) => T;

const identical: Identical<string> = (v) => v

It is interesting to note that the correct method is:

type Identical<T> = (v: T) => T;

But what exactly is causing the first example to not work and what is the type of T?

Answer №1

For the purpose of this explanation, I will define "specific" as the opposite of "generic". While some may use "concrete" to convey this idea, there is a risk of confusion with the term "abstract", which is unrelated to abstract classes.


Aside from generic functions, TypeScript only supports generic types, not generic values. To declare a generic type, the type parameter is placed in angle brackets after the type name:

type GenericType<T> = {x: T};

You can define a generic type like Foo<T>, but any actual value of that type must be specific and include a specified specific type for T:

declare const badValue1: GenericType; // error, needs 1 type argument
declare const badValue2: GenericType<T>; // error, 'T' not found
declare const goodValue: GenericType<string>; // valid

It's important to note that GenericType<string> now represents a specific type equivalent to {x: string}. Specifying generic parameters results in a specific type output.


Unlike generic types, values of generic functions are themselves generic. They encompass a variety of specific function types. In a generic function type, the type parameter comes before the function's parameter list within angle brackets:

type GenericFunction = <T>(x: T, y: T) => void;

The generic function's type itself is not generic; no type parameter appears in the GenericFunction declaration above. Therefore, you only specify the type parameter when actually calling the function:

declare const badFunc: GenericFunction<string>; // error, not a generic function
declare const goodFunc: GenericFunction; // valid
const ret = goodFunc<string>("okay", "fine"); // type parameter set as string
const ret2 = goodFunc("okay", "fine"); // type parameter inferred as string

Simply put, the distinction between these two:

 type IdGenericType<T> = (x: T) => T;
 type IdGenericFunc = <T>(x: T) => T;

lies in the fact that the first is a generic type that resolves to a specific function upon specification, while the second is a specific type representing a generic function. Although related, these types are not interchangeable. You can assign a value of type IdGenericFunc to any variable of type IdGenericType<XXX>, using any specific type XXX:

let id: IdGenericFunc = x => x;
let idString: IdGenericType<string> = id; // valid

But the reverse does not hold true:

const otherId: IdGenericFunc = idString; // error! Incompatible types

This discrepancy makes sense since an IdGenericType<string> is known to accept and return a string only:

idString = x => x + "!"; // valid

Therefore, assuming an IdGenericType<string> is identical to a valid IdGenericFunc would be inaccurate. The relationship between IdGenericType<T> and IdGenericFunc can be likened to intersecting all instances of IdGenericType<T> across all possible T values:

// type IdGenericFunc = forall T. IdGenericType<T>; // Syntax invalid

Although TypeScript lacks a direct way to represent this concept (borrowed syntax from Haskell), the fundamental distinctions remain.


To delve deeper into generic values in TypeScript, refer to the GitHub issue at microsoft/TypeScript#17574.

Code Link Here

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

Tips for testing nested HTTP calls in unit tests

I am currently in the process of unit testing a function that looks like this: async fetchGreatHouseByName(name: string) { const [house] = await this.httpGetHouseByName(name); const currentLord = house.currentLord ? house.currentLord : '957'; ...

The field value exceeds the limit of characters allowed (3184658) and should be submitted using form

This field in DTO is dedicated to storing content. @IsNotEmpty({ message: 'Nội dung này không được để trống!' }) @IsString() @MinLength(0, { message: 'Độ dài bài viết không hợp lệ!' }) content: string; While th ...

TypeORM Error: Trying to access the 'id' property of an undefined object

I attempted to implement migration in TypeORM as shown below: TableExample.entity.ts @Entity({ name: 'table_example' }) export class TableExampleEntity { constructor(properties : TableExampleInterface) { this.id = properties.id; ...

Using *ngFor to dynamically update the DOM when an array is modified via ngrx

Currently, I am utilizing *ngFor to present values from an array: [ { id: 1, name: 'item1' }, { id: 2, name: 'item2' } ] In the html: <div *ngFor="let item of (items$ | async); trackBy: trackById;&quo ...

Click the button to collapse the dropdown menu - Angular Material

Currently, I have implemented the selectTo dropdown feature in angular material design. Here is the code snippet that I am using: <mat-form-field id="inputClick" appearance="outline" (click)="Valid()"> <mat-label>{{'GENERAL.TITLE' | ...

Creating Custom Type Guards for Literal Types in Typescript: Is It Possible?

Note: I am new to using typescript. Before asking this question, I made sure to go through the documentation on advanced types and type guards. Additionally, I looked into several related questions on Stack Overflow such as user defined type guards [typesc ...

Issue: IntelliSense in VS Code is not functioning properly due to comment formatting conflicts with @types/node

I am encountering an issue with my setup in Visual Studio Code and @types/node (7.0.8). It appears that some functions have incorrectly formatted code comments, causing Visual Studio Code and Visual Studio 2017 to not display any quickinfos in IntelliSense ...

Pass data from the HTML component to the TypeScript component

When conducting a search, I prompt the user to enter the value they are looking for in my component.html. The data is then sent to the component.ts using the following code: <input class="form-control mr-sm-2" #query (keyup.enter)="search(query.value) ...

Using TypeScript with Visual Studio Code to reference a renamed file

I recently changed the name of a file from FooBar.ts to fooBar.ts. Despite updating the file name, VS Code continues to refer back to the old file. In order to resolve this issue, I disabled forceConsistentCasingInFileNames in the tsconfig.json file. Howev ...

I'm having trouble setting a value for an object with a generic type

I am attempting to set a value for the property of an object with generic typing passed into a function. The structure of the object is not known beforehand, and the function receives the property name dynamically as a string argument. TypeScript is genera ...

Using Typescript to create an index signature for easily accessing child objects through a proxy

As I am just starting to learn Typescript, please excuse me if this question is not well-formed. I have an object (Object A) that encapsulates another object (Object B) and includes some methods to manipulate Object B. My goal is to proxy the access on Ob ...

The TypeScript error message states that a value of 'undefined' cannot be assigned to a type that expects either a boolean, Connection

I've been grappling with this code snippet for a while now. It was originally written in JavaScript a few months back, but recently I decided to delve into TypeScript. However, I'm struggling to understand how data types are properly defined in T ...

Angular module with customizable configurations

I am interested in developing a customizable Angular 9 module with IVY and AOT enabled. In the latest version of Angular, IVY and AOT are automatically activated: npx @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ed8 ...

Obtain the selected type from a tuple after filtering

I have a tuple with multiple objects stored in it. const repos = [ { name: 'react', type: 'JS' }, { name: 'angular', type: 'TS' }, ] as const const RepoTypes = typeof repos const jsRepoTypes = FilterRepos<&a ...

Using TypeScript to define a generic type for the key in a React select component

Check out this component that wraps a Material UI select: return ( <Box display="flex" justifyContent={justifyContent}> <SortWrapper> <InputLabel htmlFor={id} shrink={true} > Sort by </InputLabel& ...

The prototype's function doesn't pause for anything, carrying out its duty in a continuous cycle

I have been attempting to enhance the prototype of an object by adding an asynchronous function to be called later on. Here is my approach: const ContractObject = Object; ContractObject.prototype['getBalance'] = async function(userId: number ...

Unusual class title following npm packaging

Currently, I am working on developing a Vue 3 library with TypeScript. We are using Rollup for bundling the library. Everything works as expected within the library itself. However, after packing and installing it in another application, we noticed that th ...

Experimenting with a file system library function using Jest and Typescript alongside a placeholder function

When attempting to test a library function that uses the fs module, I received assistance in this question on Stack Overflow. The feedback suggested avoiding mocks for better testing, an approach I agreed with @unional. I am now facing a similar challenge ...

Can a file be transferred from the private path to the document directory?

I wrote this code using the captureVideo() method from the Ionic Native MediaCapture plugin. Here is the file path I obtained: /private/var/mobile/Containers/Data/Application/95DB5A64-700B-4E3D-9C2C-562C46520BEC/tmp/52515367181__BBC39D42-69EC-4384-A36F-7 ...

Listening to events on the iterative variable of NgFor directive in Angular 2

Angular2 has been my latest exploration in solving a unique data binding challenge. In my UI, I've presented a javascript array of objects like a database recordset in an HTML table. Each row contains menus and inputs allowing users to modify the rec ...