1

I have the following angular typescript code.

In the function 'blendBinA' keep getting the error:

"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'ObjA'.ts(7053)"

How to fix ?

interface ObjA {
    propA: string;
    propB: number;
    propC: string[];
}

public objA: ObjA = { propA: 'Henk', propB: 23, propC: ['singel 23'] };
public objB: any = { propX: '6445 GB', propA: 'henk' };

blendBinA() {
    for (const k in this.objB) {
        if (this.objA.hasOwnProperty(k)) {
            this.objA[k] = this.objB[k];
        }
    }
}

1 Answer 1

1

This is because this.objA.hasOwnProperty(k) does not acts like a type guard.

You need to define your own custom typeguard:

const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

and then try:

interface ObjA {
  propA: string;
  propB: number;
  propC: string[];
}


const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

class Foo {

  public objA: ObjA = { propA: 'Henk', propB: 23, propC: ['singel 23'] };
  public objB: any = { propX: '6445 GB', propA: 'henk' };

  blendBinA() {
    for (const k in this.objB) {
      if (hasProperty(this.objA, k)) {
        this.objA[k] = this.objB[k];
      }
    }
  }
}

Playground

If it possible, try to type objB

P.S. It is possible to force hasOwnProperty to behave like typeguard:

See this example:

type Tag = { [prop: `tag${number}`]: never }

interface Object {
  hasOwnProperty(v: PropertyKey): boolean & Tag
}

interface CallableFunction extends Function {
  call<
    T,
    Prop extends string,
    R extends boolean & Tag
  >(this: (this: T, property: Prop) => R, thisArg: T, property: Prop): thisArg is T & Record<Prop, string>;
}

declare const obj: { name?: string, surname?: number }

if (Object.prototype.hasOwnProperty.call(obj, 'name')) {
  const test = obj.name // string
}

if (Object.prototype.propertyIsEnumerable.call(obj, 'name')) {
  const test = obj.name // string | undefined
}

Here you can find related question and answer with more explanation.

Here you will find my article with some examples

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.