Reputation: 559
I have been working in C# for quite some time and have recently begun work on a Node.js project using TypeScript V3.1.6. I was quite trilled that Typescript now supports generics which is one of the things I was anticipating loosing with the transition from C#.
My C# code is a DataRow wrapper allowing me to extract strongly typed values from a Dictionary using generics and is as follows:
Dictionary<string, object> Values = new Dictionary<string, object>();
public T Parse<T>(string columnName)
{
T result = default(T);
result = (T)Convert.ChangeType(this.Values[columnName], typeof(T));
return result;
}
My current TypeScript code is as follows:
export class DataRow {
private Values: Map<string, object> = new Map<string, object>();
constructor(row?: any) {
if (!!row) {
for (let key in row) {
this.Values.set(key, row[key]);
}
}
}
public Value<T>(key: string): T {
//Not exactly how to replicate the return.
}
}
The line in my C# code:
T result = default(T);
Allows me to return a default value for the type if the value is null. I've removed several other null checks and dictionary checks from my C# example for brevity. My primary thoughts/questions are:
1) Can you get a default type of a generic in Typescript?
2) Since I'm new to TypeScript, please feel free to point out any obvious issues with my TypeScript code thus far.
3) Will returning strongly typed values potentially influence performance in Node.js?
UPDATE:
I've updated my class to:
export class DataRow {
private Values = new Map<string, any>();
constructor(row?: any) {
if (!!row) {
for (let key in row) {
this.Values.set(key, row[key]);
}
}
}
public Value<T>(key: string): T {
if (this.Values.has(key)) {
let value = this.Values.get(key);
if (!!value) {
return value as T;
}
}
return <unknown>null as T;
}
}
It works great now. Thanks for the help!
Upvotes: 3
Views: 820
Reputation: 4602
TypeScript gives you the benefits of static typing only at build time. Your code will be compiled to JavaScript before your application can be executed in the NodeJS environment, so you don't have to worry about returning any strongly typed things, nor about the performance, as there will be no TS at all in your application at runtime.
As for your question about the default value, you can simply check for the value's existence in the map and return a default if there's nothing there.
public Value<T>(key: string): T {
if (this.Values.has(key) {
return this.Values.get(key)
} else {
// return some kind of default.
}
}
Regarding the possible improvements, I would advise you to make your class into a generic to improve type safety.
// Class is now a generic with a default type of `object`.
export class DataRow<T = object> {
// You don't need to explicitly type the Values. TS can infer that.
private Values = new Map<string, T>();
// Explicitly type the row argument for type safety.
constructor(row?: { [key: string]: T }) {
// In JS/TS land you don't have to explicitly cast
// values to booleans to be able to make a truth check.
if (row) {
for (let key in row) {
this.Values.set(key, row[key]);
}
}
}
public Value(key: string): T {
if (this.Values.has(key)) {
return this.Values.get(key)
} else {
// return some kind of a default
}
}
}
Upvotes: 1