How to Pick property based if is substring of given string in Typescript

Viewed 185

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 Answers

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

Related