tags : Web Development, Javascript, Programming Languages
Intro stuff
- JS is weakly-typed. So type-coercion can happen
- Primitive coercion: [@@toPrimitive]("default") → valueOf() → toString()
- Numeric coercion: [@@toPrimitive]("number") → valueOf() → toString()
- String coercion: [@@toPrimitive]("string") → toString() → valueOf()
 
- Primitive coercion: 
- TS is a programming language developed by Microsoft.
- Typed superset of Javascript
- Includes its own compiler.
 
Self realizations (aha moments)
- TS lets you play with types the way you play with values in a general programming language. Eg. You have a type and now you want to extract/transform parts of it into another type.
- This kind of thing you usually do with values but with typescript this is now possible. It’s sort of has a regex feel to types, in-sense what regex makes possible.
- Type functions and Values
- type ReturnWhatIPassIn<T> = T;: This right here is a function that handles- types, unlike functions that handle- valuesthat I know of in normal Javascript syntax.
- type ReturnWhatIPassIn = string;: This right here is a static value of a- type.
- So you can basically play with types just the way you play with values
 
- Just like programming with values, there are multiple ways of getting the same result. Getting better at it will take time and more doing w it.
Primitive types
- All basic types of Javascript
- any: allow anything
- unknown: ensure someone using this type declares what the type is
- never: it’s not possible that this type could happen
- void: a function which returns undefined or has no return value
Custom types
- interface- Mutable
- Good for behavior, can be extendedand merged
- Can be used for a subset of things, functions, objects etc.
 
- type- Immutable
- More features than interface
- Good for data, can be intersected(composed using |and&).
- Can be used for everything.
 
To use types or interfaces ?
- Use interface until you need to use features from type. This goes the opposite way too.
- Doesn’t really matter which one you go with.
- But some people use type by default too. It boils down to personal preferences and needs.
- My current verdict as of June’23: I’ll go w default type, if I need something that needs extending, useinterface
What about namespace?
Composing types
union
- Basically using |
- You can’t really declare them, conceptually helpful to think of them like possibilities(multiverse).
- Only typescan be union’ed notinterfaces.
- We also have discriminated unions, where there’s a common property that distinguishes what’s getting union’ed and then we can later use typeof- I think these are like variantsin Ocaml (See Type Systems)
 
- I think these are like 
generics
- Every function call has 2 argument lists
- Value arguments(runtime) : Parenthesis ()
- Type arguments(typecheck/compile time) : Pointy brackets <>
 
- Value arguments(runtime) : Parenthesis 
- We can think genericsas the type arguments, sort of fill-in-the-blanks types.
- It allows your type to more dynamic by allowing other types to be part of the original type. Eg. You couldn’t indicate the type of array at all without generics. Array<string>is using generics.
- Generics in classes and functions are different but use similar syntaxes.
- We do want to constraint the parameter into a generic if we’re doing things specific to the certain type. Usually constraint to generic parameter is added with extends. Eg.Poop<T extends string>
- For reverse constraint, you can use Objector{}to match anything butnullorundefined
Duck type
If it walks like a duck and it quacks like a duck, then it must be a duck.
TS follows duck typing. If the structure is same, you need to explicitly set the type.
interface Point {x: number; y: number;}
function logPoint(p: Point) {console.log(`${p.x}, ${p.y}`);}
const point = { x: 12, y: 26 };
const point2 = { x: 12, y: 26, z: 89 }; // this would work too! needs to be a subset
class VirtualPoint {
  x: number;
  y: number;
  constructor(x: number, y: number) {this.x = x; this.y = y;}
}
const point3 = new VirtualPoint(13, 56);
logPoint(point); // works, but point was never mentioned to be "Point"
logPoint(point2); // works, but point was never mentioned to be "Point"
logPoint(point3); // works, but point was never mentioned to be "Point"Random things
Levels of TS
- Values exist at the dynamic level.
- Types exist at the static level.
Similarly,
- Normal functions exist at the dynamic level, factories for valuesconst valueFactory = (x: number) => x; // definition const myValue = valueFactory(123); // use
- Generic types exist at the static level, factories for typestype TypeFactory<X> = X; // definition type MyType = TypeFactory<string>; // use
- Working together
function identity<Arg>(arg: Arg): Arg { return arg; } // %inferred-type: number const num1 = identity<number>(123); // %inferred-type: 123 NOTE: It's 123 and not number const num2 = identity(123);
import type
See the following
Do I need to use the import type
Index signatures
- TypeScript index signatures must be either stringornumber(alsosymbols?)
interface Cache {
  [id:string] : string;
}Type Definitions from where?
To be able to show errors and hints from other packages, the compiler relies on declaration files. Two sources,
- Bundle: check if a library has bundled types, look for an index.d.tsfile in the project.
- DefinitelyTyped: Crowdsourced repo
- Local Declarations: Define it in declarations.d.tsmaybe
declare keyword
- declare specifies a type to an already existing variable, not declaring a new one.
- eg. get external js file which has fooidentifier, tsc doesn’t know about it. So we dodeclare const foo : string, to tell the compiler that don’t worry aboutfoo, this is what it looks like it already has a type.
Asserting type
- When you know better exactly what type it would be.
- Only allows type assertions which convert to a more specific or less specific version of a type. (impossible shit not allowed)
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; const a = (expr as any) as T; // workaround if ts is too strict
- non-null assertions using !in cases where we trying to do something in an optional(?) property.
Modules in TS
- Any file containing a top-level importorexportis considered a module and is isolated.
- Any file without a top-level importorexportis considered as a script whose contents are available in the global scope
Export
- export declarations
- export statements
- re-exports
Import
- importing other modules
- explicit importing of types (guaranteed to be removed from your JavaScript, and tools like Babel can make better assumptions about your code)
Tooling
- The compiler (tsc), way to use it is via npx tsc
- tsconfig bases: https://github.com/tsconfig/bases
- I like the base/tsconfig repo, but only for CJS configurations. Some mistakes might be there for esm. verify.
- using “moduleResolution”: “node”, but using “node” as the value is telling TypeScript to emit JavaScript that resolves as a CommonJS module.
 
- what is @types??
Declaration files
- .d.ts