2

Assuming I have two interfaces:

interface A {
  a: string;
  b: string;
  x: string;
}

interface B {
  a: string;
  b: string;
}

When I have an object implementing interface A and I want to drop the property x (and the object implements interface B afterwards) - how do I tell TS what I am trying to do? Just executing delete obj.x; on the object causes TS to complain, because x is required from interface A.

Christian Engel
  • 3,738
  • 5
  • 28
  • 44
  • What do you mean by `convert`? Interfaces are just shapes. – Anatoly Dec 09 '20 at 20:09
  • https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgILIN4ChnLgLmQGcwpQBzAbh2QCNCSyQqaAPB0i6gXyy1EixEKAEKYaBYp2bVc9KUxa8ANhDB5khdAF5MeQgCJgBgDR1DAa1PJ2yAwBN7B5N2qr1tTcjG641IA – Christian Dec 09 '20 at 20:10
  • This is a strange example. Any object that is a valid `A` is also a valid `B`. No conversion is necessary. – CRice Dec 09 '20 at 20:11
  • I want to remove the property `x` from the object. TS don't want me to, because interface A says the prop should be there. – Christian Engel Dec 09 '20 at 20:12
  • I updated the wording of the question to be clearer. I want to remove property `x` from the object. – Christian Engel Dec 09 '20 at 20:15
  • 1
    `delete (obj as any).x;` will make the compiler happy. Not so pretty but it works. – Christian Dec 09 '20 at 20:17
  • Perhaps something like this would suit your needs: `const convert = (a: A): B => { const {x, ...b} = a; return b };` – CRice Dec 09 '20 at 20:21
  • Okay, both suggestions are... ugly :D I think I'll go with the idea of Christian - the answer of CRice will expand to a lot more "real" javascript code after compilation. – Christian Engel Dec 09 '20 at 20:23
  • Fair enough, but do note that a destructuring assignment is an ES6 feature and TypeScript will not transform that code if your target is ES6 or higher. – CRice Dec 09 '20 at 20:27
  • I am working with a lot of code at work that still needs to work in IE11, so I try to train my brain to rely on patterns that require fewer polyfills and generate less code after compilation :) – Christian Engel Dec 09 '20 at 20:29

2 Answers2

2

This is how I'd have done that.

interface A {
  a: string;
  b: string;
  x: string;
}

interface B {
  a: string;
  b: string;
}

function convertAtoB(a: A) {
  delete (a as any).x;
  return a as B;
}
Christian Engel
  • 3,738
  • 5
  • 28
  • 44
deb
  • 6,671
  • 2
  • 11
  • 27
0

You can use Omit or make property an optional

interface A {
  a: string;
  b: string;
  x: string;
}

interface A1 {
  a: string;
  b: string;
  x?: string;

}

const result: Omit<A, 'x'> = { a: 'a', b: 'b' }
const result1: A1 = { a: 'a', b: 'b' }

It is considered a bad practive to use delete.

Please consider next type safe example to remove object property

const removeProperty = <T, P extends keyof T>(obj: T, prop: P): Pick<T, Exclude<keyof T, P>> => {
  const { [prop]: _, ...rest } = obj;
  return rest
}

const result2 = removeProperty({ age: 2, name: 'John' }, 'name') // { age: 2 }