3

I know how to extend array for any type:

declare global {
  interface Array<T> {
    remove(elem: T): Array<T>;
  }
}

if (!Array.prototype.remove) {
  Array.prototype.remove = function<T>(this: T[], elem: T): T[] {
    return this.filter(e => e !== elem);
  }
}

Source: Extending Array in TypeScript

But is there also a way to extend the array only for a specific type?. Like only for arrays of type User -> Array<User>.

I want to create a extend method, like .toUsersMap() and this method should not be displayed for arrays, which have not the type User.

2 Answers 2

3

You can achieve similar behaviour:

type User = {
  tag: 'User'
}

interface Array<T> {
  toUsersMap: T extends User ? (elem: T) => Array<T> : never
}

declare var user: User;

const arr = [user]

arr.toUsersMap(user) // ok

const another_array = [{ notUser: true }]

another_array.toUsersMap() // This expression is not callable

If T parameter does not extends User, TS will disallow using toUsersMap

Playground

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

2 Comments

You can also use a this parameter like so.
@jcalz I believe your solution is much better than mine. Please provide an answer
2

I don't think there's a way to completely suppress the IntelliSense prompting for toUsersMap() on Arrays, but you can definitely make it a compiler error to call arr.toUsersMap() unless arr is assignable to Array<User>. One way to do this is to give the toUsersMap() method a this parameter:

interface Array<T> {
  toUsersMap(this: Array<User>): Map<string, User>;
}

Now the compiler will require that toUsersMap() only be called with a this context of something assignable to Array<User>:

interface User {
  username: string;
}
const arr = [{ username: "foo" }, { username: "bar" }];
arr.toUsersMap() // okay, no error

const another_array = ["hello", 123];
another_array.toUsersMap() // error, 
//~~~~~~~~~~~ <--
// The 'this' context of type '{ notUser: boolean; }[]' is 
// not assignable to method's 'this' of type 'User[]'

Playground link to code

Comments

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.