Эквивалент частного наследования в Typescript (только включая или исключая определенные члены класса или свойства) - PullRequest
1 голос
/ 14 апреля 2019

Каков наилучший способ имитации частного наследования в Typescript? В частности, класс chid хочет скрыть определенных членов родительского класса.

Например, ожидаемый обходной путь должен достигать следующего:

Класс CustomArray<T> расширяется от Array<T> и скрывает определенных членов, скажем, только pop() и shift().

let c1 = new CustomArray<number>();
c1.push(10, 20, 30, 40, 50); // okay
c1.shift(); // should error
c1.pop();   // should error
c1.sort(); // okay  etc...

Вот то, что я пытался, но vscode все еще допускал, что якобы ограниченный член.

//Try to hide pop() and push():
type T1<T> = Exclude<Array<T>, 'pop'| 'push'>

// check
let x: T1<number> = [];
x.push(3);  // allowed -- okay
x.pop();    // also allowed -- but wanted it to be an error

1 Ответ

3 голосов
/ 14 апреля 2019

Вы не хотите использовать наследование, потому что вы не намерены разрешить использование CustomArray<T> одинаково, как Array<T>.

Что вы можете сделать, это определить свой новый тип как функцию Array<T> и сделать конструктор CustomArray таким же, как конструктор Array во время выполнения:

type CustomArray<T> = Pick<Array<T>, Exclude<keyof Array<T>, "shift" | "pop">>;
const CustomArray: new <T>() => CustomArray<T> = Array;

let c1 = new CustomArray<number>();
c1.push(10, 20, 30, 40, 50); // okay
c1.shift(); // error
c1.pop();   // error
c1.sort(); // okay 

Тоработает так, как вы просили.Но имейте в виду, что это «поверхностное» преобразование Array<T>.Например, метод sort() будет по-прежнему возвращать Array<T>, а не CustomArray<T>:

c1.sort().pop(); // okay

Если вы действительно хотите «глубокое» преобразование, при котором все соответствующие упоминания Array<T> заменяются на CustomArray<T>, вам, возможно, придется пойти дальше и вручную указать полный интерфейс, так как автоматическое сопоставление вряд ли будет работать так, как вы хотите:

interface CustomArray<T> {
  length: number;
  toString(): string;
  toLocaleString(): string;
  // pop(): T | undefined;
  push(...items: T[]): number;
  concat(...items: ConcatArray<T>[]): CustomArray<T>;
  concat(...items: (T | ConcatArray<T>)[]): CustomArray<T>;
  join(separator?: string): string;
  reverse(): CustomArray<T>;
  // shift(): T | undefined;
  slice(start?: number, end?: number): CustomArray<T>;
  sort(compareFn?: (a: T, b: T) => number): this;
  // ... ALL the other methods, omitted for brevity
} 
const CustomArray: new <T>() => CustomArray<T> = Array;
const c1 = new CustomArray();
c1.push(10, 20, 30, 40, 50); // okay
c1.shift(); // error
c1.pop();   // error
c1.sort(); // okay  
c1.sort().pop(); // error

Это более утомительно, но вы можете осуществлять намного больший контрольза результат.Любой способ должен работать для вас, хотя.Надеюсь, это поможет;удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...