5

My goal is to type removeUrl function:

type MyType = {
  name: string;
  last_name: string;
  children_url: string;
  children2_url: string;
  children3_url: string;
  // ...
}

function removeUrls(target: MyType): MagicType {
  const result = {}
  for (const key in target) {
    if (!key.includes('_url')) {
      result[key] = target[key]
    }
  }

  return result;
}

This may be a simple question but I'm new to typescript generics world and it's quite difficult to find any good google results to this problem :/

1 Answer 1

8

This is not possible on typescript 4.0.


But on the unreleased 4.1 beta via Template Literal Types you have some options!

If you're new to typescript this will look a bit strange:

type UrlKeys<T> = {
  [K in keyof T]: K extends `${infer Prefix}_url` ? K : never
}[keyof T]

type RemoveUrls<T> = Omit<T, UrlKeys<T>>

The UrlKeys type iterates over an objects properties. For each key, if the key K has some Prefix followed by a _url at the end, then return that key name, else return never. The [keyof T] at the end gets a union of all the keys that were not assigned to never.

Then RemoveUrls simply takes a type and Omits any keys that would be considered _urls.

You would use those types like this:

function removeUrls<T>(target: T): RemoveUrls<T> {
  const result: Partial<T> = {}
  
  for (const key in target) {
    if (!key.includes('_url')) {
      result[key] = target[key]
    }
  }

  return result as T;
}

const result = removeUrls({ a: 123, b_url: 'http://example.com' }) // type: { a: number }

Note that this function is now has the T generic parameter to accept any type. And the return value is the the same type, minus the url properties.

Also, when building an object one property at a time like this, you would need to type the in progress object as a Partial to make it okay that not all properties are present while being constructed. Then in the return statement, you can cast it back to a full T since you know you have processed all the properties.

Playground

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

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.