microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101k stars 12.48k forks source link

generic type interface with template literal string wrong generate implemented function #43029

Open siosio34 opened 3 years ago

siosio34 commented 3 years ago

TS Template added by @mjbvz

TypeScript Version: 4.3.0-dev.20210228

Search Terms


Steps to Reproduce:

i make generic type interface with template literal string, and i use implements this type in class. but vscode quick auto make interface feature wrong work. please look below screenshot.

image

i expect when i use implements interface and auto make interface function, setName(arg: string), setAddress(arg: number) maked . but in present name: (arg: string) and address: (arg:number) maked. so make type error in vscode...

image

but when i make this function myself, not make type error in vscode...

why generate implement function code wrong work with template literal string?

Does this issue occur when all extensions are disabled?: Yes

mjbvz commented 3 years ago

Please share the text of the code along with screenshots

siosio34 commented 3 years ago

@mjbvz here my full code! thank you

type NonFunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;

type IBuilder<T> = {
  [k in keyof NonFunctionProperties<T> as `set${Capitalize<string & k>}`]: (
    arg: T[k]
  ) => IBuilder<T>;
};

interface NoParamConstructor<T> {
  new (): T;
}

class BuilderCommon<T> {
  public object: T;

  constructor(ctor: NoParamConstructor<T>) {
    this.object = new ctor();
  }

  build(): T {
    return this.object;
  }
}

class House {
  name: string;
  address: number;

  constructor() {
    this.name = "";
    this.address = -1;
  }

  setName(arg: string) {
    this.name = arg;
    return this;
  }

  setAddress(arg: number) {
    this.address = arg;
    return this;
  }

  getNameAndAddress() {
    return `${this.name}_${this.address}`;
  }

  getAddressPlusString(arg: string) {
    return arg + this.address;
  }
}

class HouseBuilder extends BuilderCommon<House> implements IBuilder<House> {
  constructor() {
    super(House);
  }

  setName(arg: string) {
    this.object.name = arg;
    return this;
  }

  setAddress(arg: number) {
    this.object.address = arg;
    return this;
  }
}

new HouseBuilder().setName("#21").setAddress(123).build();

``
siosio34 commented 3 years ago

@RyanCavanaugh hmm... if you time is okay, can you tell me what fix file for fix this bug?

Matrixbirds commented 3 years ago

I have same problem, you can reproduce here.

a-tarasyuk commented 2 years ago

The latest version of TS doesn't suggest Implement interface QF for this case. I think there are two ways: mark this issue as fixed or try to make definitions from Symbol without declarations (current case omit QF because symbol doesn't declarations)

https://github.com/microsoft/TypeScript/blob/719ab0b47721c7dfe72708d8771f6778f2de58c3/src/services/codefixes/helpers.ts#L62-L64

@RyanCavanaugh @DanielRosenwasser @andrewbranch What do you think?

andrewbranch commented 2 years ago

It would be nice for this to work still. We should be able to generate an implementation just from the type structure, no syntax needed. (I was actually surprised to learn recently that the implement interface fix does rely so heavily on the syntax of the declaring interface.)

a-tarasyuk commented 2 years ago

@andrewbranch Oke, thanks