important
This is a contributors guide and NOT a user guide. Please visit these docs if you are using or evaluating SuperTokens.
TypeScript
Use typed strings as much as possible. For example, if a
stringvariable can have a certain values, do not assign it typestring, but instead use"val1" | "val2" ...Use
typeinstead ofinterfacesornamespace.Classes must start with a capital letter, but variables with a small letter.
No
switchstatements, useif, elseinstead.Camel case is preferred over using underscores.
Minimise use of old JS style coding:
- use classes instead of prototypes
- use arrow functions whenever possible (except for when implementing recipe / api interfaces. See https://github.com/supertokens/supertokens-node/issues/199)
- no use of
var, always uselet
Always use
===and never==Always do explicit
ifchecks. For example, ifvar1: string | undefined, do not doif (var1), instead, doif (var1 !== undefined). The only time something likeif(var2)is acceptable, is when the type ofvar2: boolean.if the return type of a function is an object, then specify the object's type in the function signature. If the object is used in several places, create a
typefor it in atypes.tsfile, and reference that.If the return type of a function is an object that has a different structure based on the logic of the function, then use the
|operator. For example, a return type can be:{status: "OK", name: string} | {status: "FAILED"} // goodWe prefer the above as opposed to
{status: "OK" | "FAILED", name?: string} // badbecause the second option expresses more possible types that what is possible -
namewill always beundefinedifstatus: "FAILED".Also notice that we have a common field (
status) across the different object types. This is necessary since if we don't have this, then the consumer of the return type would have a hard time knowing what the structure is.Minimise the use of
null. By convention, we preferundefinedovernull.Minimise the use of
anyandunknown. But if we must use these, we prefer usingany.Whenever creating an exportable module (to the user), we must allow them to import like:
import T from ".."and then doT.A()import { A } from "..."and then doA()
We want to minimise the number of named types. Otherwise this can grow to a very long list, very quickly.
Miscellaneous functions like
checkEmailFormat, orconvertToBase64()can go into autils.tsclass. No need to create separate files for them.Use
@deprecatedto deprecate functions and classes. When using this, make sure to use it in all functions that use the deprecated function as well (if applicable). If a user facing function needs to be deprecated, make sure to check that that's happening by using the playground.