Encountering a "property is missing in type { [key: string]: any; }" error while using TestCafe typed Context

Despite my experience using Typescript, I still come across challenges that stump me from time to time.

In a recent Github issue, the function passed into any test hook using a typed context is causing an error:

Property 'color' is missing in type '{ [key: string]: any; }' but required in type 'MyContext'

The code snippet from the Github issue triggering the problem is as follows:

interface MyContext {
    color: string
}

interface TestControllerEx<TContext> extends Omit<TestController, 'ctx'> {
    ctx: TContext;
}

fixture`Fixture1`.beforeEach(async (t: TestControllerEx<MyContext>) => {
    t.ctx.color = 'red' // strongly typed!
});

test('Test1', async (t: TestControllerEx<MyContext>) => {
    await t.expect(t.ctx.color).eql('red'); // 'red' strongly typed!
});

To work around the issue, I have made the color property in MyContext optional. However, I am keen to understand the root cause of this problem.

The TestController interface in TestCafe types the ctx property as { [key: string]: any }. Shouldn't the generic type passed into TestControllerEx fulfill this requirement? I have attempted having TContext extend the { [key: string]: any } index signature directly without success.

Is this issue related to TestCafe's typings or am I overlooking something specific to Typescript?

I would greatly appreciate any assistance. Thank you!

Answer №1

From what I understand, there isn't a straightforward way to accomplish your objective. One workaround is to create a custom FixtureFn interface and utilize the fixture object as its implementation.

get-fixture-with-custom-ctx.ts script:

import 'testcafe';

export function getFixtureWithCustomCtx<MyContext> () {
    interface TestControllerEx extends TestController {
        ctx: MyContext;
    }

    // @ts-ignore
    interface MyFixture extends FixtureFn {
        beforeEach: (fn: (t: TestControllerEx) => Promise<any>) => MyFixture;
    }
    return fixture as MyFixture;
}

test.ts file:

import { getFixtureWithCustomCtx } from './fixture';

interface MyContext {
    color: string;
}

const fixture = getFixtureWithCustomCtx<MyContext>();

fixture`My fixture`
    .page('about:blank')
    .beforeEach(async t => {
        t.ctx.color = 'red';
        t.ctx.style = 'inline';
    });

test('Test1', async t => {
    await t.expect(t.ctx.color).eql('red');
});

By following this approach, TypeScript rules will only be broken in one specific file where you export the fixture with the desired context for use anywhere else.

Answer №2

In this specific scenario, the use of Typescript is essential. The example shows how TestControllerEx extends all properties from TestController at the top level without doing so for embedded properties like ctx. It then proceeds to override the properties of ctx with a more robust type. This restriction ensures that arbitrary values cannot be assigned to the ctx property. To tackle this issue, an additional definition can be added in the MyContext, as demonstrated below:

import { Selector } from 'testcafe';

interface MyContext {
    color: string;
    [key: string]: any;
}

interface TestControllerEx<TContext> extends Omit<TestController, 'ctx'> {
    ctx: TContext;
}

fixture`Fixture1`.beforeEach(async (t: TestControllerEx<MyContext>) => {
    t.ctx.color = 'red' // strongly typed!
    t.ctx.style = 'inline ' // strongly typed!
});

test('Test1', async (t: TestControllerEx<MyContext>) => {
    await t.expect(t.ctx.color).eql('red'); // 'red' strongly typed!
});

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

Angular6 HttpClient: Unable to Inject Headers in Get Request for Chrome and IE11

Under my Angular 6 application, I am attempting to make a GET request while injecting some custom Headers: Here is how my service is structured: @Injectable() export class MyService { constructor(public httpClient: HttpClient) { } getUserInfos(login): Ob ...

How can Angular JS handle multiple validators being triggered at once?

Hey there, I'm currently working with validators in my Angular form setup. Here's a snippet of how it looks - I utilize Validators.compose to combine custom validators. The errors from these validators are then displayed on the HTML component. My ...

Using Angular to display asynchronous data with ngIf and observables

In cases where the data is not ready, I prefer to display a loader without sending multiple requests. To achieve this, I utilize the as operator for request reuse. <div class="loading-overlay" *ngIf="this.indicatorService.loadingIndicators[this?.indic ...

React.js TypeScript Error: Property 'toLowerCase' cannot be used on type 'never'

In my ReactJS project with TSX, I encountered an issue while trying to filter data using multiple key values. The main component Cards.tsx is the parent, and the child component is ShipmentCard.tsx. The error message I'm receiving is 'Property &a ...

When working with Typescript, an error is thrown if property "p" does not exist on one of the classes that are OR

In my component class, I have a property called renderContent which can be of either LessonPageType or TaskPageType based on the input value. Below is the code snippet from my component: import {ChangeDetectionStrategy, Component, HostListener, Input, OnI ...

Ways to retrieve object array values

How can I extract object array values from a data array? Here is the code I am using: Component FmtNews(mediasource) { let body = mediasource; console.log("Testing body:" +body) this.commonService.getTopNews(body) .subscribe((res) => { ...

writing a react element in an object with an svg component

I am encountering difficulties when trying to type the following. The problem lies with the TeamIcon. Here is how my object is declared. import TeamIcon from './components/icons/TeamIcon'; export const teamObject: Record< string, Recor ...

Spartacus has the capability to extend or override the PageType enum within the cms.model framework

I am facing a dilemma similar to the Spartacus situation. In brief, I am required to modify the PageType enum in cms.model by either overriding or extending it. The current enum consists of four values (content, product, category, catalog) and I must incl ...

Enhancing Type Safety with TypeScript in 2020: A User-Friendly Approach

It is widely understood that TypeScript conducts type-checking solely at compile-time. While there are existing methods, like io-ts, to incorporate runtime checks, I can't help but wonder if a more straightforward approach exists. For instance, cons ...

create a promise type for a function in TypeScript

I came across this code recently and I'm curious about why it specifies the return type as Promise. Since the function is returning data, which is an object, what's the purpose of adding | null at the end? const getSomething = async ( id: stri ...

What could be causing the presence of a "strike" in my typescript code?

While transitioning my code from JavaScript to TypeScript for the first time, I noticed that some code has been struck out. Can someone explain why this is happening and what it signifies? How should I address this issue? Here's a screenshot as an exa ...

Looking to transform a psql query into typeorm syntax

I am in search of data on a daily, weekly, or monthly basis. I utilized the date_trunc() function to generate such records. Although I was successful in creating a psql query, I am unfamiliar with typeorm stack and need guidance on converting it into typeo ...

Using localStorage in an Angular template: a comprehensive guide

Currently, I am facing some issues with localStorage on a website as I am unable to get a * ngif directive to function as desired. To provide further context: When a user logs in, their information is stored in the localStorage under the 'identity&ap ...

Cannot assign argument of type 'string | undefined' to parameter expecting type 'string'. Typescript is being strict

While attempting to update an object using the SDK and having 'strict' mode enabled in typescript, I encountered the following error: const offer = client.offer(oldOfferDefinition!.id); await offer.replace(newOfferDefinition); error TS2345: Argu ...

Generating exports while utilizing the UseReducer hook method for a React application

My React hooks application includes a special actions file when userReducer is used, as shown below: export namespace PrepareReviewActions { export enum Types { TOGGLE_CONFIRMATION, TOGGLE_ALL_CHECKED, SET_EXCEPTION_TYPES, SET_ACTION_ ...

react-hook-form replaces the onChange function causing delays in updating the value

Recently, I created a unique Select component utilizing useState and onChange. I attempted to integrate this custom component with the powerful react-hook-form. Allow me to share the code snippet for the bespoke Select component. const Select = forwardRef ...

The array used within the useEffect hook and the getCoordinates function appears to be distinct when printed with console

Utilizing GoogleMap API for Custom Location Display I have an imported array of JSON objects named data which includes an address property. The Google Maps API is used to retrieve coordinates from the addresses in order to generate custom markers displaye ...

The error message "Type 'null' cannot be assigned to type 'Element | DocumentFragment'" occurs when using Nextjs/React createPortal

I am completely new to typescript. Currently, I'm working on a project that has a lot of pre-configured react components in JavaScript files (.js). My task now is to convert everything to TypeScript (.tsx) without triggering any ESLint errors. Unfort ...

Unable to transmit props while employing Typescript in ReactJS

Attempting to pass props from components like AllProducts, MenProducts, etc. to the AddToCartButton component for reusability presents a challenge. When trying to pass props using: <AddToCartButton id={product.id} /> An error is encountered: Type & ...

Enhance the efficiency of the algorithm for combining text nodes that contain decorations

I'm seeking assistance in merging two arrays of nodes along with their decorations. My current algorithm is functional but highly inefficient. I would appreciate any suggestions for improvement or new ideas. Each node within the arrays contains text, ...