Please ensure that the function chain has appropriate parameter and return types by specifying the tuple type

Can a new type be created for the given tuple/array that has certain validation constraints?

The following array is considered valid:

const funcs = [(a: string) => 1, (a: number) => 'A', (a: string) => 2]

However, this one is invalid due to a change in return types:

const funcs = [(a: string) => 1, (a: number) => 2, (a: string) => 3]

The key difference is the return type of the middle function being modified from string to number.

Is there a way to achieve this through TypeScript?

type SubtractOne<T extends number> = [-1, 0, 1, 2, ...][T];
type AddOne<T extends number> = [1, 2, 3, 4, ...][T];

const funcs = [(a: string) => 1, (a: number) => 'A', (a: string) => 2]

type CheckFuncs<T extends any[]> = { [(K extends number) in keyof T]: T[AddOne<K>] }

type funcsType = typeof funcs
type funcsType2 = CheckFuncs<funcsType>

A potential solution involves indexing with mapping. Could this method be applied to perform addition or subtraction using AddOne on K? This would enable access to the ReturnType of T[K] and the Parameter<T[k+1]>[0].

Playground

Answer №1

To access the next or previous value of a tuple using an index type K, you can utilize the power of variadic tuple types. You can define a type called Tail<T> that takes a tuple type T and returns a new tuple with the first element removed:

// Tail<[1,2,3]> is [2,3]
type Tail<T extends readonly any[]> = T extends [any, ...infer R] ? R : never;

With this definition in place, you can express "T[K+1]" as Tail<T>[K].

This answers your initial question, but let me continue to demonstrate how you can use it:


Here's a starting point for defining your CheckFuncs type:

type CheckFuncs<T extends readonly ((x: any) => any)[]> = { [K in keyof T]:
    K extends keyof Tail<T> ? (
        [T[K], Tail<T>[K]] extends [(x: infer A) => infer R, (x: infer S) => any] ? (
            [R] extends [S] ? T[K] : (x: A) => S
        ) : never
    ) : T[K]
}

This code walks through the tuples in T, compares T[K] with Tail<T>[K], and adjusts T[K] so that it works correctly. You can then create instances like these (ensure to use const assertions to preserve the tuple type):

const pass = [(a: string) => 1, (a: number) => 'A', (a: string) => 2] as const
const fail = [(a: string) => 1, (a: number) => 3, (a: string) => 2] as const

These produce the following types:

type passType = CheckFuncs<typeof pass>
// readonly [(a: string) => number, (a: number) => string, (a: string) => number]

type failType = CheckFuncs<typeof fail>
// readonly [(a: string) => number, (x: number) => string, (a: string) => number]

You can also create a function that works with CheckFuncs as demonstrated below:

function useFuncs<T extends readonly ((x: any) => any)[]>(...t: CheckFuncs<T>) { }

useFuncs((a: string) => 1, (a: number) => 'A', (a: string) => 2); // success
useFuncs((a: string) => 1, (a: number) => 3, (a: string) => 2); // error!
// ----------------------> ~~~~~~~~~~~~~~~~
// Argument of type '(a: number) => number' is not assignable to 
// parameter of type '(x: number) => string'.

Your implementation of CheckFuncs may vary based on your requirements. This serves as an example to guide you. Best of luck!

Link to code

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 is the most effective way to code and define a MatSelect's MatSelectTrigger using programming techniques?

How can I programmatically set the MatSelectTrigger template for a MatSelect instance using the provided reference? The documentation mentions a settable customTrigger property, but information on the MatSelectTrigger class or how to create one dynamically ...

Error encountered when running protractor cucumber test: SyntaxError due to an unexpected token {

Embarking on the journey of setting up Protractor-Cucumber tests, I have established a basic setup following online tutorials shared by a kind Samaritan. However, upon attempting to run the tests, I encountered an error - unexpected token for the imports. ...

Tips for creating a versatile function in TypeScript that accepts either a single value or an array of values for two parameters

I'm currently working on a task to develop a versatile function that accepts a parameter called hashMapName, another parameter called 'keys' which can be either a string or an array of strings, and a callback function that will return either ...

Is scanf capable of handling massive char arrays without breaking?

I am encountering an issue with reading a string of triple digit-digit-space. Below is the relevant code snippet, which may or may not require additional libraries: #include <stdio.h> #include <stdlib.h> #define N 20 #define M 20 #define n (3 ...

Enhance the appearance of data in Angular using a pipe or alternative method

Currently in my Angular 8 application, I have some data displaying in a div like so: {"Information":"Information one","Output":[{"address1":"someaddress"},{"address2":"someaddress"},{"address3":"someaddress"},{"address4":"someaddress"}]} However, it&apos ...

What is preventing me from assigning to a class variable within a $http success handler?

During the course of my project, I have encountered a perplexing situation that is difficult to comprehend. My intuition tells me that the issue lies in a peculiar nuance of javascript while I am working in TypeScript. Unfortunately, I am unable to prove t ...

Typescript's interface for key-value pairing with generic types

Consider the example Object below: let obj1: Obj = { 'key1': { default: 'hello', fn: (val:string) => val }, 'key2': { default: 123, fn: (val:number) => val }, // this should throw an error, because the types of d ...

Issue with useEffect() not receiving prop

Currently diving into the world of React and still in the learning process. I recently integrated a useEffect() hook in my code: import { fetchDetails } from "../../ApiServices/Details"; export interface RemoveModalProps { id: number; i ...

Establishing the initial state in React

Can someone help me with setting the default state in React? I'm working on a project that allows files to be dropped onto a div using TypeScript and React. I want to store these files in the state but I'm struggling with initializing the default ...

Using Row-Major Ordering in C with Command Line Parameters

Looking to input a 2D area in the form of a matrix from a txt file through the command line. Here is an example format: 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 Working with C and aiming for row-major order, attempting this approach: int matr ...

What is the best way to calculate the total of a set of strings that represent

Query: Converting array string elements to integers for summation. Check out my code: str = ["+7", "-3", "+10", "0"] str.map!(&:to_i) sum = 0 str.each do |num| if num.is_a?(Integer) sum += num end end puts sum The issue: Traceback (most r ...

Developing a word-building game inspired by Scrabble using C programming. Implementing a method to determine specific characters in a string, followed by assigning each character a score based on an array

Currently enrolled in CS50, I have been tasked with creating a game similar to "Scrabble". Here are the key details of the implementation: The objective is for two players to input words, and the player with the highest score emerges as the winner. Points ...

What is the best method to find a matching property in one array from another?

I am working with two arrays in TypeScript. The first one is a products array containing objects with product names and IDs, like this: const products = [ { product: 'prod_aaa', name: 'Starter' }, { product: 'prod_bbb&apos ...

Utilizing Selenium TestNG: Implementing DataProvider with 1D Array to Enhance Yahoo Search Feature

When I attempted to perform a search using Yahoo search, I encountered an issue where only the first element in the array was being searched. Interestingly, the same code works fine for Google search. Here is the code snippet: package googleSearch; impor ...

TS2322 error: What does it mean when the type is both not assignable and assignable?

I've been delving into the world of generics with Java and C#, but TypeScript is throwing me for a loop. Can someone shed some light on this confusion? constructor FooAdapter(): FooAdapter Type 'FooAdapter' is not assignable to type 'A ...

The input '{ data: InvitedUser[]; "": any; }' does not match the expected type 'Element'

I'm currently facing a typescript dilemma that requires some assistance. In my project, I have a parent component that passes an array of results to a child component for mapping and displaying the information. Parent Component: import { Table } fr ...

The WebSocket connection in the browser, when accessed through a remote server, typically shows a CLOSED state in the readyState property during the on

Local server operations are running smoothly. However, when testing on a remote server with Nginx, the issue arises where the readyState inside the event handler onopen is consistently showing as CLOSED. Nginx configuration: server { server_name doma ...

Manipulating nested arrays using index values in JavaScript

Can someone assist me in sorting a multidimensional array based on the value of the first index? I've tried using a for loop without success. Looking for solutions in JS or jQuery. I want to convert the following array: var pinData = [ ['< ...

Issue: The system encountered a critical error: attempting to use a string offset as an

An issue has occurred: Attempting to use a string offset as an array in C:\xampp\htdocs\includes\categories\categories.php on line 12 $categories[$parent][] = $row; categories.php <?php $sql = "SELECT catid, catn ...

The dropdown navigation bar fails to close upon being clicked

I'm currently facing an issue with the navbar in my project. The bootstrap navbar doesn't close automatically after clicking on a link. I have to move my mouse away from the navbar for it to close, which is not ideal. Additionally, I'm worki ...