-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Private properties required when assigning an instance of a different class with the same public interface #16556
Comments
That's the intended design for type PublicPart<T> = {[K in keyof T]: T[K]}; //keyof only sees public properties
class ComplexClass {
public firstField: string;
public secondField: string;
private thirdField: string;
}
class NormalClass {
public firstField: string;
public secondField: string;
}
function complexFunction(param: PublicPart<ComplexClass>) {
console.log(param.firstField);
console.log(param.secondField);
// done, I can't use other properties of a ComplexClass object
}
complexFunction(new NormalClass()); // no error But I think the "unnecessary" interface is actually what you want, since it specifies the shape of the data you care about. Even with class NormalClass implements PublicPart<ComplexClass> or, forget about class NormalClass {
public firstField: string;
public secondField: string;
}
class ComplexClass extends NormalClass {
private thirdField: string;
}
function normalFunction(param: NormalClass) {
console.log(param.firstField);
console.log(param.secondField);
// done
}
normalFunction(new NormalClass()); // no error
normalFunction(new ComplexClass()); // no error |
I understand what your saying but not always I have access to the type of the parameter, if an external library instead of typing a parameter with an interface is using a class with private/protected fields (I know that it's wrong but it could happens) and for example I want to make a dummy/stub for it I need to either: In a different language it would be different but this is typescript and in absence of private fields I can assign the parameter without any problems. Another example: // External library
class ComplexClass {
public firstField: string;
public secondField: string;
}
// External library
function complexFunction(param: ComplexClass) {
console.log(param.firstField);
console.log(param.secondField);
// done, I can't use other properties of a ComplexClass object
}
// Personal Application
class NormalClass {
public firstField: string;
public secondField: string;
}
// Personal Application
complexFunction(new NormalClass()); // this works This example works but it's odd that with a simple implementation change in the ComplexClass (adding the I have read your link but I can find only how private fields work but not why it works like that, I really like to know the reason for that decision, I'm curious to see where I'm wrong at this point! |
Read through #471 to see a discussion about this. I think casting is the only solution if you don't have access to the class definition or parameter typings. You can do this sort of safely with something like: function mock<T>(instance: PublicPart<T>): T {
return <T>instance;
}
complexFunction(mock<ComplexClass>(new NormalClass())); |
I found an example in that discussion, I translate it with my example classes: class ComplexClass {
public firstField: string;
public secondField: string;
private thirdField: Function = () => {};
public static doSomething(cc: ComplexClass): void {
cc.thirdField();
}
}
class NormalClass {
public firstField: string;
public secondField: string;
}
const normal: NormalClass = new NormalClass();
ComplexClass.doSomething(normal); // Fails Now I understand why we can't accept an object based only on his public interface. Thanks for the answers! |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
TypeScript Version: 2.3.4
Code
Expected behavior:
Typescript compiles correctly.
Actual behavior:
Comments:
The public interface of ComplexClass is what the function complexFunction is expecting to use (properties
firstField
andsecondField
) but Typescript is expecting the developer to pass a parameter that mirrors also the private properties.Is this done on purpose?
To make it work I need to create an unnecessary interface:
Not always I have control on the type of the input parameter of the function so this solution is not applicable. Why the parameter of the function does not accept an object with the same public interface?
The text was updated successfully, but these errors were encountered: