From https://github.com/Microsoft/vscode/issues/46286
TypeScript Version: 2.8.0-dev.20180320
Search Terms:
Code
interface IFoo {
x?: number
y: number
}
class Foo implements IFoo {
}
Trigger implement interface on Foo
Expected behavior:
Only required properties required:
interface IFoo {
x?: number
y: number
}
class Foo implements IFoo {
y: number;
}
Actual behavior:
Both required and optional properties added:
interface IFoo {
x?: number
y: number
}
class Foo implements IFoo {
x?: number;
y: number;
}
Why is this expected? It's much easier to delete the optional properties/methods you don't want than to track down the entire hierarchy of the target interface looking for them. We could add a comment or something or split it out into two commands if needed, but just opting them out feels like a regression in functionality.
My expectation is that the quick fix will fix the error by adding the required stubs, nothing more.
React's component interface is a good example of why I don't think optional properties should be added by default. It has a bunch of optional lifecycle methods that you only need in specific cases
The behavior described here still takes place, and seems related to this issue. Is the root issue here the compiler should offer two options: implementing required members, and implementing _all_ members (if applicable)?
If so, would it be possible to bubble up the latter option to IDEs even when rule 2420 is not being violated? This could be used, for instance, as a hotkey shortcut in VS Code for fully implementing an interface even when the "red squigglies" are not appearing.
Just a motivation example for React.Component:
import * as React from 'react';
class C implements React.Component { // implement interface here
}
Results in:
import * as React from 'react';
class C implements React.Component {
context: any;
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K>) | Pick<{}, K>, callback?: () => void): void {
throw new Error('Method not implemented.');
}
forceUpdate(callback?: () => void): void {
throw new Error('Method not implemented.');
}
render(): React.ReactNode {
throw new Error('Method not implemented.');
}
props: Readonly<{}> & Readonly<{children?: React.ReactNode;}>;
state: Readonly<{}>;
refs: {[key: string]: React.ReactInstance;};
componentDidMount?(): void {
throw new Error('Method not implemented.');
}
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean {
throw new Error('Method not implemented.');
}
componentWillUnmount?(): void {
throw new Error('Method not implemented.');
}
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void {
throw new Error('Method not implemented.');
}
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>) {
throw new Error('Method not implemented.');
}
componentDidUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>, snapshot?: any): void {
throw new Error('Method not implemented.');
}
componentWillMount?(): void {
throw new Error('Method not implemented.');
}
UNSAFE_componentWillMount?(): void {
throw new Error('Method not implemented.');
}
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void {
throw new Error('Method not implemented.');
}
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void {
throw new Error('Method not implemented.');
}
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void {
throw new Error('Method not implemented.');
}
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void {
throw new Error('Method not implemented.');
}
}
Most helpful comment
Why is this expected? It's much easier to delete the optional properties/methods you don't want than to track down the entire hierarchy of the target interface looking for them. We could add a comment or something or split it out into two commands if needed, but just opting them out feels like a regression in functionality.