Verify the type without making any assumptions about the checked type

Take a look at this type definition:

interface ISmth<T> {
  id: number;
  data: T;
}

Now, I am interested in creating an array that contains elements of this type:

var a = [{
  id: 1,
  data: [],
}, {
  id: 2,
  data: 4,
}, {
  id: 3,
  data: "abc",
}] as const

I am using as const to indicate that this array is immutable and it includes various types for the data property that I would like to differentiate.

However, I also want TypeScript to ensure that each element in the array adheres to the ISmth<any> structure. How can I enforce this validation?

Answer №1

There are two methods to impose type restrictions on a:

Type assertion at compile time only

@Qwertiy proposed this solution, which utilizes an interface that extends the never type in case of a failed type assertion to trigger a compile error. Additionally, a compile error can be generated by using a generic type constraint. By allowing the assertion type to be generic and accept multiple types, it could be implemented as shown below (Playground):

type AssertAssignable<T, U extends T> = true

var a = [{
    id: 1,
    data: [],
}] as const

var aError = [{
    id: "foo",
    data: [],
}] as const

type Assert = AssertAssignable<readonly ISmth<any>[], typeof a> 
type AssertError = AssertAssignable<readonly ISmth<any>[], typeof aError> // error(OK!)

Type assertion utilizing a helper function (originally from here)

A helper function named createA can be created with the sole purpose of enforcing types on the object literal created for a, while still maintaining strict typing via as const (Playground):

function createA<A extends Readonly<ISmth<any>[]>>(a: A): A {
    return a
}

var a = createA([{
    id: 1,
    data: []
}] as const);

var aError = createA([{
    id: "1", // error (OK!)
    data: []
}] as const);

You can also perform the assertion inline using an IIFE, if createA is not used elsewhere:

var aInline = (<A extends Readonly<ISmth<any>[]>>(a: A) => a)([{
    id: 1,
    data: [],
}] as const)

... or create a versatile utility helper that can be exported.

function enforceTypedLiteral<T>() {
    return <A extends T>(a: A) => a
}

enforceTypedLiteral<readonly ISmth<any>[]
>()([{
    id: 1,
    data: []
}] as const)

Answer №2

Check this out:

interface ISomething<T> {
  id: number;
  data: T;
}

var arr = [{
  id: 1,
  data: [],
}, {
  id: 2,
  data: 4,
}, {
  id: 3,
  data: "abc",
}] as const

type Type = (typeof arr extends Readonly<ISomething<any>[]> ? Object : never);
interface Y extends Type { }

If the condition is satisfied, Type represents Object and code will compile.
Otherwise, if not met, Type is never, interface cannot extend never leading to an error.

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

React form submissions are not saving the state

I currently have dynamic components rendered from the server side, including a submit button component. The issue I am facing is that when I submit the form, the state reverts to its initial values instead of retaining the updated values set by child compo ...

What is the best way to apply a filter to an array of objects nested within another object in JavaScript?

I encountered an issue with one of the API responses, The response I received is as follows: [ {type: "StateCountry", state: "AL", countries: [{type: "County", countyName: "US"}, {type: "County", countyNa ...

Tips for setting up nested folders using Node.js on a Windows machine:

Is there a way to use Nodejs in Windows 10/11 to create a parent folder and then add a new folder inside of that parent folder, like this: parent/child within the Documents folder? ...

Struggling with getting Typescript async/await to function properly

I'm experiencing an issue with async/await in TypeScript targeting es2017. Here is the code snippet that's causing trouble: My route.ts : method: 'POST', config: { auth: { strategy: &apo ...

Using WebdriverIO with Angular to create end-to-end tests in TypeScript that involve importing classes leads to an error stating "Cannot use import statement outside a module."

I am facing an issue while trying to set up a suite of end-to-end tests using wdio. Some of the tests utilize utility classes written in TypeScript. During the compilation of the test, I encountered the following error: Spec file(s): D:\TEMP\xx& ...

Using TypeScript or JavaScript, set object keys as fields of a class

I am looking for a way to update the properties of this class dynamically using an object export default class Foo { private accessKey: string; private workspaceId: string; private api: AxiosInstance; public bar: string; public name: s ...

Result of Mongodb aggregation operation

I've created a Property controller : //Retrieve Properties By Type const getPropertiesByType = async (req: Request, res: Response) => { const { cities, type } = req.query; const citiesArr = typeof cities === 'string' ? cities.spli ...

Can you explain the significance of using curly braces in an import statement?

The TypeScript handbook has a section on Shorthand Ambient Modules, where an import statement is shown as: import x, {y} from "hot-new-module"; It doesn't explain why y is in curly braces in the above statement. If both x and y were inside the brace ...

Tips for preventing the overwriting of a JSON object in a React application

I'm trying to compare two JSON objects and identify the differing values in the second JSON object based on a specific key. My goal is to store these mismatched values in a new JSON object. The current issue I'm facing is that when there are mult ...

Issue encountered with Ionic and ssh2: process.binding is not supported

I am currently delving into the world of Ionic and experimenting with creating a basic application that utilizes SSH2 to establish an ssh connection between the app and a server. Here is a breakdown of the steps I took to encounter the issue: Steps to Rep ...

What is the best way to export an overloaded function in TypeScript?

Trying to figure out how to overload a function in TypeScript so it can determine the type of arg2 based on the value of arg1. Arg1 has a list of known values. Here's a rough example of what I'm attempting: interface CatArgs {legs : number} int ...

State management in React using hooks

Recently, I've been grappling with form validation while working on a signup form for my React app using Next.js. I've noticed that many sign up pages typically hide an "invalid" message until the user interacts with an input field. I attempted t ...

Tips for simulating or monitoring an external function without an object using Typescript 2 and Jasmine 2 within an Angular 4 application

In order to verify if a function called haveBeenCalledWith() includes the necessary parameters, I am seeking to validate the correctness of my call without actually executing the real methods. I have experimented with multiple solutions sourced from vario ...

After calling the service, Angular 2 is unable to perform any actions within the subscribe method

I am struggling with what to do after authenticating my user. Once I receive the data, I want to redirect them to the appropriate page based on their role and display their name on that page. I have tried various methods, but it seems like when I try to ca ...

When the route is changed, the system must execute a function to verify the authenticity of the token

When routing changes in Angular, I have a requirement to execute a function based on whether a valid token is set or not. Is there anyone who can assist me in achieving this task? In Angular 1, I used to accomplish this using $on. ...

Develop a TypeScript utility function for Prisma

Having trouble inferring the correct type for my utility function: function customUtilityFunction< P, R, A extends unknown[] >( prismaArgs /* Make "where" field optional as it is already defined inside findUnique method below */, fn: ( pris ...

Issue with ReactJS Typescript: Cannot assign type 'number' to type '0, 8, 16, 24, 32, 40, or undefined'

I am looking to implement a grid from material-ui in react using typescript. You can view the live demo here. I have made adjustments to the example to make it work with typescript. Here is how my demo.jsx file looks like: import { withStyles } from &apo ...

Utilizing a Material UI custom theme in React with Typescript: A step-by-step guide

Upon using the tool , I received a js file and a json file following the paths mentioned on the theme generator page: // src/ui/theme/index.js /* src/ui/theme/theme.json */ The files operate smoothly when left with the .js extension. However, when I attem ...

Ionic storage is unable to assign a number as a string

My goal is to store all numbers retrieved from the function getWarrentsNumber() in ionic storage, but I encountered an error. Error: The argument of type "number" cannot be assigned to type 'string'. this.storage.set(this.NumberOfAssignedWarren ...

Why is TypeScript giving an error about an undefined object key, even though the key was assigned a value in the previous command?

type MaybeThereIsAValue = { [p: string]: string | undefined } ... let bar: MaybeThereIsAValue = {}; const key = "carpe"; bar[key] = "diem"; const why = bar[key]; // why is string | undefined I am confused as to why why is showing ...