How to define a private property when implementing an interface in Typescript? - reactjs

I'm using TypeScript in my project and I have come across an issue.
I'm defining an interface like this:
interface IModuleMenuItem {
name: string;
}
I want to create a class that implements from this interface but I want the name to be a private property like this:
class ModuleMenuItem implements IModuleMenuItem {
private name: string;
}
I'm getting the following error:
Class ModuleMenuItem incorrectly implements interface IModuleMenuItem.
Property name is private in type ModuleMenuItem but not in type
IModuleMenuItem.
How can I define a property as private or protected when implementing an interface?

Interfaces define "public" contracts and as such it doesn't make sense to have protected or private access modifier on interfaces, which are more of a, let's call it, implementation detail. For that reason you can't do what you want with an interface.
If you want to make the property read-only to consumers, but overridable in a subclass then you can do something like this:
interface IModuleMenuItem {
getName(): string;
}
class ModuleMenuItem implements IModuleMenuItem {
private name;
public getName() {
return name;
}
protected setName(newName : string) {
name = newName;
}
}
I think in TypeScript 2.0 (not out yet) you will be able to use the readonly access modifier if you were after initialization-time readonly field - https://basarat.gitbooks.io/typescript/content/docs/types/readonly.html
interface IModuleMenuItem {
readonly name : string;
}
class ModuleMenuItem implements IModuleMenuItem {
public readonly name : string;
constructor() {
name = "name";
}
}

I think you may do it like this
interface IModuleMenuItem{
name: string
}
class ModuleMenuItem implements IModuleMenuItem {
private _name: string;
constructor() {
_name = "name";
}
get name(){
// your implementation to expose name
}
set name(value){
// your implementation to set name
}
}

In case of having private fields in class, you need to introduce setter and get methods for that field like so:
export class Model {
private _field: number;
get field(): number {
return this._field;
}
set field(value: number) {
this._field= value;
}
}
And then create the interface as usual (We can not use private modifier for interface fields) like so:
export interface IModel {
field: number;
}
Then implement it to our class like so:
export class Model implements IModel {
...
}
TypeScript will understand that this model is implemented correctly the interface as we have introduced set and get method.

The only way you can have an inner state and assign interface to that instead of class and make that state private
class A{
private state:IA = ...
}

As an addendum to Syntax's response, there is no need to include a setter. A getter method is all that is needed. This could be used, for example, for read-only variables set at initialization, though I suppose it's better to use the readonly modifier in this case.
interface IModuleMenuItem
{
name: string;
}
class ModuleMenuItem implements IModuleMenuItem{
private name$: string;
constructor(name: string)
{
this.name$ = name;
}
public get name()
{
return this.name$;
}
}

Use abstract classes instead.
Composition over inheritance.
interface AppInterface {
app: express.Application
port: string | number
}
abstract class AbstractApp implements AppInterface {
app: express.Application
port: string | number
constructor(){
this.app=express()
this.port=8080
}
protected defaultMiddlewares(): void {}
}
class App extends AbstractApp {
constructor() {
super()
}
protected defaultMiddlewares(): void {
this.app.use(express.json())
}
}

Related

Can I switch between two collections under same DB in java spring-boot application?

I have mongodb related code in my java application and can I switch between two collections under same db in java code ?
#JsonIgnoreProperties(ignoreUnknown = true)
#Document(collection = "collectionA")
#QueryEntity
public class RepreCase {
I want to have a different collection here instead of this say collectionB #Document(collection = "collectionA") and comeback to the same collectionA, by switching between the two collections A & B under same DB
Can I do like this ? #Document(collection = "collectionA, collectionB")
Is it achievable & How ? Thanks in advance
This example should help
Define your entity class like
#Document(collection = "${EventDataRepository.getCollectionName()}")
public class EventData implements Serializable {
Define a custom repository interface with getter and setter methods for "collectionName"
public interface EventDataRepositoryCustom {
String getCollectionName();
void setCollectionName(String collectionName);
}
Provide implementation class for custom repository with "collectionName" implementation
public class EventDataRepositoryImpl implements EventDataRepositoryCustom{
private static String collectionName = "myCollection";
#Override
public String getCollectionName() {
return collectionName;
}
#Override
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
}
Add EventDataRepositoryImpl to the extends list of your repository interface in this it would look like
#Repository
public interface EventDataRepository extends MongoRepository<EventData, String>, EventDataRepositoryImpl {
}
Now in your Service class where you are using the MongoRepository set the collection name, it would look like
#Autowired
EventDataRepository repository ;
repository.setCollectionName("collectionName");

Can abstract classes have arrays?

In typescript, is it possible to have an array inside an abstract class, then add or push an item in that array?
abstract class Department {
private data: string[] = [];
addData(item: string) {
this.data.push(item);
}
constructor(public name: string) {}
printName(): void {
console.log("Department name: " + this.name);
}
abstract printMeeting(): void;
}
Yes, you can do that. It's exactly like doing it in a non-abstract class, you just mark it abstract:
abstract class Example {
private data: string[] = [];
addData(item: string) {
this.data.push(item);
}
}
This won't be useful unless you subclass it (class SomethingElse extends Example...).

TypeScript - What is the syntax of an array of objects which are children of an abstract class?

I have this TypeScript inheritance hierachy, Person is the base abstract class.
Whereas the class Man & class Woman are descendants of the abstract Person class.
The abstract class Person has a property called _children which are an Array of the abstract Person object.
I need to add an Array of children to my Woman and Man class.
But I guess I can't add an Array of the Person object, because it's abstract.
Instead I need to add the descendant objects Man & Woman to the Array.
Could you tell me what the syntax of this construct is?
So I need an Array which can contain Man & Woman objects.
When I try to do this:
private children: Person[] = [this.womanA, this.manB, this.womanD, this.manC];
private manD: Man = new Man(this.children, 'Lyngby');
I am getting the error:
Uncaught ReferenceError: Person is not defined at Object../src/app/_models/Man.ts
abstract class Person {
private _children: Person[];
constructor(children: Person[]) {
this._children = children;
}
}
export class Woman extends Person {
private _shoesize: number;
constructor(children: Person[], shoesize: number) {
super(children);
this._shoesize = shoesize;
}
}
export class Man extends Person {
private _favteam: string;
constructor(children: Person[], favteam: string) {
super(children);
this._favteam = favteam;
}
}

Typewriter: generate TypeScript parameter properties

Currently I am using Typewriter for automatic generation of TypeScript class from my C# classes. Lets say I have this very simple C# class:
[Dto]
public class MyDto
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
Also I have this simple typewriter template:
$Classes(c => c.Attributes.Any(x => x.Name == "Dto"))[
export class $Name {
constructor(
$Properties[
public $name: string,
]
) { }
}]
The issue I have with this template is that there is a trailing comma after the last constructor parameter property in the generated ts class:
export class MyDto {
constructor(
public prop1: string,
public prop2: string, /* <---- notice the comma here */
) { }
}
I would like to have the properties of the C# class generated as parameter properties in the TypeScript class, but with the example above the generated TypeScript is not valid. Is there a way to achieve this with a Typewriter template?
To answer my own question: I amended the template like this:
$Classes(c => c.Attributes.Any(x => x.Name == "Dto"))[
export class $Name {
constructor(
$Properties[
public $name: string][,]
) { }
}]

Serialize a derived class without access to base class

I need to serialize a derived class in my Windows Phone 7 Project for tombstoning state.
But I don't have access to the code to the base class - exposed by a Library -.
//don't have access to this class
public class A
{
public string member1 {get;set;}
}
[DataContract]
public class B : A
{
public B(){}; //CTOR
[DataMember]
public string member2 {get;set;}
}
When the system try to serialize (I save it to PhoneApplicationPage.State => so it's auto serializing) : it's not working, the exception (InvalidDataContractException) says "Type 'B' cannot inherit from a type that is not marked with DataContractAttribute or SerializableAttribute. Consider marking the base type 'A' with DataContractAttribute or SerializableAttribute, or removing them from the derived type."
Should I implement a custom serializer ? How can I do that (in Windows Phone 7)
Rather than derive from the library class, you could have a member variable that of that type and expose the properties of the library class member via custom getters and setters:
[DataContract]
public class MyClass
{
BaseClass Wrapped { get; set; }
public MyClass()
{
Wrapped = new BaseClass( );
}
[DataMember]
public string member1
{
get { return Wrapped.member1; }
set { Wrapped.member1= value; }
}
}

Resources