What is the process for defining an opaque type in programming?

[ This is not this ]

Take a look at this snippet of code:

interface Machine<OpaqueType> {
    get(): OpaqueType,
    update(t: OpaqueType);
}

const f = <U, V>(uMachine: Machine<U>, vMachine: Machine<V>) => {
    const u = uMachine.get();
    vMachine.update(u);
}

The error shown when trying to compile the last line reads as follows: “Argument of type 'U' is not assignable to parameter of type 'V'. 'V' could be instantiated with an arbitrary type which could be unrelated to 'U'.”

Indeed! I have two machines that can each handle their own parts independently but not together without explicit coordination.

However, the usage of <U, V> seems unnecessary. The function doesn't really care about the specific types involved. It would be ideal to write it in a simpler way like this:

const f = (uMachine: Machine<unknown>, vMachine: Machine<unknown>) => {
    const u = uMachine.get();
    vMachine.update(u);
}

This version should also be flagged for compilation errors since one unknown type may not necessarily align with another unknown type.

Is there a way to communicate this requirement using Typescript?

Edit: It's important that the second version does not compile. I want the compiler to catch any mistakes in this scenario.

Answer №1

Could it be a possibility that you are in search of just one generic type parameter instead of two?

const f = <T,>(machine1: Machine<T>, machine2: Machine<T>) => {
    const data = machine1.get();
    machine2.update(data);
}

These two machines can have any types as long as they match, but they cannot collaborate if their types differ.

Answer №2

If you want to use vMachine.update(u), then the type U must be compatible with the type V. This can be ensured in your generic function by specifying a constraint that requires U to extend V.

const f = <U extends V, V>(uMachine: Machine<U>, vMachine: Machine<V>) => {
    const u = uMachine.get();
    vMachine.update(u);
}

Now, the Machine<U> which provides the value must have an underlying type that can be accepted by Machine<V>.

For example, if you have two machines where one accepts a union of string literals and the other accepts any string:

declare const machineStringLiteral: Machine<'abc' | 'def'>
declare const machineAnyString: Machine<string>

When using the function f:

f(machineStringLiteral, machineAnyString) // valid
f(machineAnyString, machineStringLiteral) // error
// Argument of type 'Machine<string>' is not assignable to parameter of type 'Machine<"abc" | "def">'.
//   Type 'string' is not assignable to type '"abc" | "def"'.(2345)

This behavior is expected because a general type like string cannot be assigned to specific string literals such as

"abc" | "def"

Check playground for demonstration

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

The specified property is not present in the type '{}'

I've been incorporating Typescript into my React application Within my mapStateToProps, this is the code I'm using const mapStateToProps = (state: AppState) => { console.log(state) return { ...state.player, position: ...

Issue with Typescript and react-create-app integration using Express

I'm relatively new to Typescript and I decided to kickstart a project using create-react-app. However, I encountered an issue while trying to connect my project to a server using express. After creating a folder named src/server/server.ts, React auto ...

Explicit final argument in TypeScript

Is it feasible to define a function in TypeScript 2.7.2 and above with variable parameters, but ensuring that the final parameter has a specific type? I am attempting to craft an ambient TypeScript declaration for a JavaScript library that utilizes functi ...

Error Encountered: Unhandled Runtime Error in Next.js with Firebase - TypeError: Unable to access the property 'initializeApp' as it is undefined

It's baffling why this error keeps appearing... my suspicion is directed towards this particular file. Specifically, firebaseAuth={getAuth(app)} might be the culprit. Preceding that, const app = initializeApp(firebaseConfig); is declared in "../f ...

Retrieving a result from the reduce function in Angular

Is there a way to use the reduce function in order to return a list of objects? I am currently only able to return a single object with keys as project names and values as hours: { Name1: 9, Name2: 10, Name3: 30, } What changes can I make to my code to ac ...

Is it possible to encounter an unusual token export while trying to deactivate Vue with veevalidate

Utilizing Nuxt with server side rendering. Incorporating Typescript along with vee-validate version 3.4.9. The following code has been validated successfully extend('positive', value => { return value >= 0; }); Upon adding the default, ...

What is the process for parameterizing a tuple in coding?

In my scenario, I have a tuple with interrelated types. Specifically, it involves an extractor function that retrieves a value, which is then used as input for another function. What I envision conceptually looks like this code snippet, although it does n ...

What is the best way to verify that I am receiving the 'jwt' token in my code?

Trying to understand the data held by the jwt token in my next.js app, but encountering an error message saying error: jwt must be provided. Here's the code snippet causing the issue: import { NextRequest } from "next/server" ...

Using Vue-router and Typescript with beforeEnter guard - utilizing validated data techniques

As I utilize Vue along with vue-router and typescript, a common scenario arises where a single page is dedicated to displaying a Photo component. A route includes a beforeEnter guard that checks my store to verify the existence of the requested photo. ...

Invoking a method in a derived class upon completion of asynchronous logic within the base class

Currently, I am in the process of building an Angular application. One aspect of my project involves a class that extends a base class. While this approach may not be ideal, I am curious to know what would be the best practice for BaseClass to trigger me ...

Implementing intelligent parameter type enforcement according to configuration settings

I can't decide on a name for this concept, so please be patient while I explain it. There are three configuration objects: const configA = { type: 'A' as const, getPath: (query: { foo: string }) => `/${query.foo}` } const config ...

Encountering TS1204 error on version 1.5.0-beta with ES6 target, yet all functionalities are running smoothly

After successfully compiling everything from Typescript to ES6 to ES5, I encountered an error that has me stumped. The error message reads as follows: Error TS1204: Cannot compile external modules into amd or commonjs when targeting es6 or higher. Here i ...

Using React TypeScript to trigger a function upon route changes with react-router-dom

I am trying to use the useEffect hook to console log every time the location changes in my project. However, when I try to compile, I receive an error in the terminal saying Unexpected use of 'location' no-restricted-globals. I would like to fin ...

How can a custom event bus from a separate account be incorporated into an event rule located in a different account within the CDK framework?

In account A, I have set up an event rule. In account B, I have a custom event bus that needs to act as the target for the event rule in account A. I found a helpful guide on Stack Overflow, but it was specific to CloudFormation. I am providing another a ...

The module "install-npm-version" could not be located

I am currently working on a project using TypeScript, which you can find at this GitHub repository. However, when I attempt to use the package in another project, I encounter an error that says Cannot find module 'install-npm-version'. Steps to ...

Oops! The program encountered an issue on the production environment, but it's running smoothly

When I execute Webpack using the command node node_modules/webpack/bin/webpack. js --env. prod An error message is displayed below. However, when running in --env. dev mode, the command executes without any issues. Can't resolve './../$$_gen ...

Error: Astra connection details for Datastax could not be located

Currently, I am attempting to establish a connection to DataStax Astra-db using the cassandra-client node module. Below is an example of my code: const client = new cassandra.Client({ cloud: { secureConnectBundle: 'path/to/secure-connect-DATABASE_NA ...

Troubleshooting Issue with Mongoose Virtual Field Population

I am currently facing an issue with my database due to using an outdated backend wrapper (Parse Server). The problem arises when dealing with two collections, Users and Stores, where each user is associated with just one address. const user = { id: &q ...

Develop a TypeScript class in a distinct file

I currently have ag-grid implemented in an Angular project with a CustomFilter. The problem is that the file containing the code for the CustomFilter function is becoming quite large and difficult to manage. I am now looking to move the CustomFilter to a s ...

Firebase Cloud Function Local Emulator Fails to Retrieve Data with Error 404

My goal is to locally trigger a Firebase Cloud Function using the emulator. However, every time I try, the function returns a 404 Not Found status code and a response body of Cannot Get. The function is deployed locally and visible on the UI, but it fails ...