3

I am trying to define custom types in TypeScript with some additional extension methods, also want to allow other uses of my library to extend this type as well.

Want to implement the toJson method and more utility functions, I tried to do that by creating two files: domain.d.ts with this code:

export type TermOperator = '=' | '>' | '<' | '!=' | '<=' | '>=' | 'in' | 'not in' | 'like';
export type DomainOperator = '&' | '|' | '!';

export type Term = [left: string, operator: TermOperator, right: string | number | Date | EnumType | undefined | boolean];
export type ScalarDomain = [...Array<DomainOperator | Term>];

export interface Domain extends Array<ScalarDomain | Domain | DomainOperator | Term>
{
    toJson(): string;
    flat(): [string | number | Date | EnumType | boolean | undefined];
    parse(): void;
}

and tried to add new file domain.extension.ts with the following code:

Domain.prototype.toJson = function (){ return 'json object'; }

But I am getting errors such as:

Error TS2693 (TS) 'Domain' only refers to a type, but is being used as a value here.

don't know exactly how to achieve this, as I am a beginner in JavaScript.

For more context, here is how I am planning to use this code:

const term1: Term = ['name', '=', 'amine'];
const term2: Term = ['age', '>', 25];
const term3: Term = ['address', 'like', 'eloued'];

const domain1: Domain = ['|', term1, term2, '&', term3];
const domain2: Domain = ['&', term1, term2, '&', ['city', '=', 'Malaga']];
const domain3: Domain = [domain1, domain2];

const jsonStr: string = domain3.toJson();
2
  • 1
    Focus on one question at a time here. Please edit your question to include details on just one of these problems, then you post a new question for the other if necessary. And if you could include a minimal example that demonstrates any errors you are getting, that would help ensure you get an answer. Commented Jul 25, 2022 at 21:55
  • Types and Interfaces don't mean much when they are compiled from TS to JS. They are just compile-time typing "contracts". If you have a Type or Interface that requires a method, then implement it as a class. Or, create plain JS objects that conform to your Types/Interfaces with those functions as members. Or, implement the method as a standalone function that accepts your Type/Interface. Don't try to give types and interfaces their own functionality - that's not what they're used for in TS. In your example, I think Domain should probably be a class. Commented Jul 25, 2022 at 22:00

1 Answer 1

2

A type cannot add functionality.

All that this does:

const domain1: Domain = ['|', term1, term2, '&', term3];

is tell Typescript that domain1 is expected to be of type Domain, and if it's not then a type error will be shown. It does not, and cannot, change the features on the array that is being assigned to this variable.

Imagine all type annotations were removed. Would your code work? Because that's exactly what happens when your code executes.


If you want to provide additional methods to this array, you would typically wrap that value in a class that allows you declare those other methods.

For example:

export class Domain {
    constructor(public terms: ScalarDomain) {}

    toJson() {
      return JSON.stringify(this.terms)
    }

    flat() {
      return this.terms.flat()
    }

    parse() {
      console.log('implete parse here')
    }
}

Which you would use like:

const term1: Term = ['name', '=', 'amine'];
const term2: Term = ['age', '>', 25];
const term3: Term = ['address', 'like', 'eloued'];

const domain1 = new Domain(['|', term1, term2, '&', term3]);
domain1.toJson() // fine

See playground


Or a more functional approach would be to create functions that accept your data and do things with them.

function domainToJson(domain: Domain) { return JSON.stringify(domain) }
function domainFlat(domain: Domain) { return domain.flat() }

const term1: Term = ['name', '=', 'amine'];
const term2: Term = ['age', '>', 25];
const term3: Term = ['address', 'like', 'eloued'];

const domain1: Domain = ['|', term1, term2, '&', term3]
domainToJson(domain1) // fine

See playground

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, Alex, I know about using classes as I am coming from C#, but I don't like to use the new keywords, want it implicitly converts to the class or my type or interface.
I know there is an alternative approach using interfaces, but don't know how to do it, as it looks complicated a bit.
A type cannot add functionality. An interface is is a kind of type. In Javascript/Typescript there is no such thing as an implicit conversion to a class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.