#Help me understand generic class interfaces

72 messages Β· Page 1 of 1 (latest)

dark aurora
#

Is my understanding correct that the below class is a generic type that requires all fields coming from the inferred interface of SomeOtherClass?

export class MyClass<T extends SomeOtherClass> extends SomeOtherClass {...}

In other words, if SomeOtherClass implements an interface called OtherInterface, and this interface looks like this:

interface OtherInterface {
  someField: string;
}

Then MyClass has to have a static property that is of type string called someField, but in addition it can have any other type of property, because it is a generic T?

At least this is what I was trying to achieve with the above.

unkempt ruin
#

I think you're mixing up a bunch of different concepts

#

namely inheritance, generics, and static properties

dark aurora
#

Thanks @unkempt ruin, I think I can understand if you explain it to me.

unkempt ruin
#

Then MyClass has to have a static property that is of type string called someField
not static, but will have an instance property someField: string
but in addition it can have any other type of property, because it is a generic T?
it can have other properties, since it's extending a class
the generic is completely irrelevant tho

dark aurora
#

Hi, your understanding is partially correct.
When you define MyClass like this, it inherits all properties and methods of SomeOtherClass the generic T is a type that extends SomeOtherClass, but it doesnt automatically add new properties to MyClass

#

You can use T for creating new properties or methods inside MyClass that depend on the type T

merry thistleBOT
#
Ascor8522#7606

Preview:```ts
class A {
// A has a field a of type string
a!: string
}

class B extends A {
// B is A (it has the a property) plus some other fields (b)
b!: string
}

interface I {
i: string
}

class C implements I {
// MUST have all properties and methods defined in
...```

dark aurora
#

Ok, maybe I understand you now. So it can have other instance properties regardless since it extends the SomeOtherClass. But if I want those to be typesafe, writing <T extends Surreal> like I have done is correct as long as I pass the type when I use the new keyword?

#

yes you can pass the type like this when creating a new instance of the class: new MyClass<SomeOtherClassLike>()

unkempt ruin
#

But if I want those to be typesafe, writing <T extends Surreal> like I have done is correct as long as I pass the type when I use the new keyword?
yes
the type extends Surreal describes the "minimum shape" T must have
so the property of type T inside your class will have all the properties of the Surreal type

dark aurora
#

One last question, is TS inferring the type of the Surreal class?

#

that ^^, I like "minimum shape" πŸ˜„

unkempt ruin
#

is TS inferring the type of the Surreal class?
it can, if the type T is used somewhere in a prameter or return type of the function/constructor

dark aurora
#

you can use Classes just like types/interfaces in TS i think

dark aurora
#

so yes it should infer the type

#

Is there any good overview documentation that describes the basics of where in JavaScript we can write TypeScript. I see TypeScript written using <> and I see it using :.

For example, when I attempted to write new MyClass<MyType>() I did not know whether <> should be placed before or after the class name. Is there some rule that I should know?

unkempt ruin
#

he basics of where in JavaScript we can write TypeScript
huh?

dark aurora
#

Yeah, strange questions, I know πŸ™‚

unkempt ruin
#

TypeScript IS JavaScript plus some added type system

dark aurora
#

: is the return type of type of the variable, so it comes after the () of the function or after the variable name

unkempt ruin
#

I see TypeScript written using <> and I see it using :
not sure what you mean by that
<> (also known as the "diamond operator" in other language) is used for generics in TypeScript
: can be used in a lot of different places

  • JS/TS object litterals ({ foo: "bar" })
  • TS types (function foo(param: Type): OtherType { [...] })
  • JS/TS ternary opertor (condition ? true : false)
    note the teranry operator can also be used in TS for types (conditional types) (T extends Type ? TypeA : TypeB)
dark aurora
#

<> can also be the parameters of another type like Record<string, number>

#

Thank you @unkempt ruin and @dark aurora!

#

I guess there is no point in typesetting a static class, since you mentioned that classes are themselves considered to be a sort of type and their properties by themselves define its type?

#

I assume it only makes sense to typeset instances, since those are dynamic.

unkempt ruin
#

so yeah, use the class as type for the concrete and "abstract" types

dark aurora
#

Thank you very much!

#

I would only use generics for "dynamic" things, just like the default TS types,

Promise<boolean> // promise knows that it has to resolve with a boolean
Record<string, number> // keys can only be string and all values must be numbers

so only generics are only useful when you allow some "customization" if you know what I mean

#

and let TS infer things itself whenever it can

#

Thank you, that is a good rule of thumb. And also we shouldn't define types for everything, only if it does not have a type and cannot infer.

unkempt ruin
#

we shouldn't define types for everything, only if it does not have a type and cannot infer.
that's debatable
basically comes down to personnal preferences

dark aurora
#

There is one complication, which is that if we rely on a type soehwere in our code and we remove that piece of code, TS may scream at us.

#

defining more types can also help the TS compiler to avoid some performance issues, but thats rare

unkempt ruin
dark aurora
#

Now that I know a bit more about TS, maybe my TS will break πŸ˜›

dark aurora
#

they can be global, but you can also use typeof someVar then it could be considered local

unkempt ruin
#

usually at the tope of the file if they are also needed elsewhere (exported)
maybe near the bottom if they are only used in that file and that file only (utility types)
and in some rare cases, if the type is only used within the function

dark aurora
#

I have never written an "abstract" type. Like MyType is a function that returns something. But I have seen some syntax that looks something along the lines of Type MyType = () => string

#

So far, I have applied my types on the objects themselves. In what part of the TS documentation can I learn the syntax for writing such "abstract" types as mentioned above?

unkempt ruin
#

definitely the "type manipulation" section

#

it's part of the slightly more "advanced" stuff of the language

dark aurora
dark aurora
unkempt ruin
dark aurora
#

const x = 22;
// this is TS (inside the type)
const y: typeof x = 5;
#

so y gets the type of x

dark aurora
unkempt ruin
dark aurora
#

its very useful when you dont want to repeat yourself too much:

class X {
 profile = {name: string; age: number};
 ...

 addNewProfile(p: typeof this.profile) {...}
}
#

Ok, nice, so here you are defining a type that is only visible inside the class context

#

But shouldn't it be Type profile?

#

its good to learn what is TS and what is JS, this will help you identify it.
I mean TS = "only the types stuff"

dark aurora
#

Oh now I see, it is the JS operator you are using

#

In combination with the TS :

#

so in that class, only the : typeof this.profile is TS types
is pure JS you also cannot define the profile like that, but might be soon

#

"The typeof operator returns a string indicating the type of the operand's value."

#

right, so like Ascor said,
TS is just JS... but with some extras

dark aurora
#

That makes sense why MS decided to call it typeof in that case.

dark aurora
#

Thank you both very much, TS is pretty tricky and fun πŸ™‚

dark aurora
#

!resolved