在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
最佳答案
您不希望使用继承,因为您不打算允许使用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
这比较麻烦,但是您可以对结果进行更多控制。不管哪种方法对您都有效。希望能有所帮助;祝好运!