Luckylooke
Luckylooke

Reputation: 4539

Typescript toUpperCase() conversion is not accepted

I have source type defined as:

unit: 'hour'|'day'|'week'|'month'

I am using it as lowercase for moment.js library. Bu I also need it uppercase for backend endpoint. So my http method accepts parameter as

unit: 'HOUR'|'DAY'|'WEEK'|'MONTH'

But the typescript does not accept conversion via toUpperCase in method call.

Argument of type 'string' is not assignable to parameter of type 'HOUR'|'DAY'|'WEEK'|'MONTH'

enter image description here

Is there an elegant solution in typescript that I will not destroy static type checking and in the same time I will not make extra convertor helper function (custom toUpperCase)?

Thanks for advices! :)

Upvotes: 5

Views: 2704

Answers (2)

kareem alkoul
kareem alkoul

Reputation: 817

Depend on previous answer you can make the extend of declaration more generic with TypeScript predefine

interface String {
  toUpperCase<T extends string>(this: T): Uppercase<T>;
}

Upvotes: 1

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

You can extend the declaration of toUpperCase to have an extra overload that takes this specific union of string literal types and returns the upper case version of the union type. There is no extra function, just an extra compile time declaration:

interface String {
    toUpperCase(this: 'hour'|'day'|'week'|'month') : 'HOUR'|'DAY'|'WEEK'|'MONTH'
}

declare let low: 'hour'|'day'|'week'|'month';
let up = low.toUpperCase(); // typed as "HOUR" | "DAY" | "WEEK" | "MONTH"

Note

If you are in a module you will need to redeclare string in the global namespace:

declare global {
    interface String {
        toUpperCase(this: 'hour' | 'day' | 'week' | 'month'): 'HOUR' | 'DAY' | 'WEEK' | 'MONTH'
    }
}

Upvotes: 6

Related Questions