286 Matching Annotations
  1. Dec 2021
  2. Nov 2021
    1. export interface TasksListSpecifics { 0: ('parallel' | 'sequential'); } export type TasksList = (string[] & TasksListSpecifics); Or more compact: export type TasksList = (string[] & { 0: ('parallel' | 'sequential'); }); The trick is to add your more specific properties on top of array of string type (Array<string>).
    2. add ! to the end of the var that is being spread. E.g. [{}, ...payload!]
    1. Notice that in the else branch, we don’t need to do anything special - if x wasn’t a string[], then it must have been a string.
    2. Animal & { honey: boolean }
    3. Extending a type via intersections
    4. Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.
    1. I suggest renaming this to something like SomeInterfaceAsTypeWrittenByHand. Because one of the reasons for Simplify is so you don't have to write SomeType by hand. Then add the following to show that Simplify<SomeInterface> is the same as SomeInterfaceAsTypeWrittenByHand. declare const a: Simplify<SomeInterface>; expectType<SomeInterfaceAsTypeWrittenByHand>(a); // Interface is assignable to its Simplified type (created with Simplify, and by hand) expectType<Simplify<SomeInterface>>(someInterface); expectType<SomeInterfaceAsTypeWrittenByHand>(someInterface);
    1. const palette: { [key: string]: string } = {...
    2. Regarding mapped types, remember that { [K in T]: U } is a special form - it can't be combined with other properties within the { }. So there's not really a name for the [K in T: U] part because it's just part of the overall "mapped type" syntax { [K in T]: U }
    3. what is the TypeScript Way™ of handling the implicit any that appears due to object literals not having a standard index signature?
    4. fresh (i.e. provably do not have properties we don't know about)
    5. Object literals don't have index signatures. They are assignable to types with index signatures if they have compatible properties and are fresh (i.e. provably do not have properties we don't know about) but never have index signatures implicitly or explicitly.
    6. Which... is confusing because Palette technically does have an index signature Palette is a mapped type, and mapped types don't have index signatures. The fact that both use [ ] is a syntactic coincidence.
    7. type PaletteColors = keyof typeof palette type Palette = { [Color in PaletteColors]: string }
    8. Generate type with the index signature: interface RandomMappingWithIndexSignature { stringProp: string; numberProp: number; [propName: string]: string | number | undefined; }
    9. we have no way to know that the line nameMap[3] = "bob"; isn't somewhere in your program
    1. The other commenters are right about the potential solutions. However, it is actually considered a best practice to move the object with the index signature to a nested property.Said differently: No property in the object with the index signature should depart from how the index signature is typed.
    2. Like others have noted, your function does not conform to index signature. [key: string]: string means "all fields are strings" and on the next line you declare a field with function in it.This can be solved by using union types:type IFoo = { [foo: string]: string } & { fooMethod(fooParam: string): void }
    1. you can define locally parse and it should take precedence over the one in the library: interface JSON { parse(text: string, reviver?: (key: any, value: any) => any): unknown; }
    2. This PR adds a new top type unknown which is the type-safe counterpart of any. Anything is assignable to unknown, but unknown isn't assignable to anything but itself and any without a type assertion or a control flow based narrowing. Likewise, no operations are permitted on an unknown without first asserting or narrowing to a more specific type.
    1. So now the question is, why does Session, an interface, not get implicit index signatures while SessionType, an identically-structured typealias, *does*? Surely, you might again think, the compiler does not simply deny implicit index signatures tointerface` types? Surprisingly enough, this is exactly what happens. See microsoft/TypeScript#15300, specifically this comment: Just to fill people in, this behavior is currently by design. Because interfaces can be augmented by additional declarations but type aliases can't, it's "safer" (heavy quotes on that one) to infer an implicit index signature for type aliases than for interfaces. But we'll consider doing it for interfaces as well if that seems to make sense And there you go. You cannot use a Session in place of a WithAdditionalParams<Session> because it's possible that someone might merge properties that conflict with the index signature at some later date. Whether or not that is a compelling reason is up for rather vigorous debate, as you can see if you read through microsoft/TypeScript#15300.
    2. why is Session not assignable to WithAdditionalParams<Session>? Well, the type WithAdditionalParams<Session> is a subtype of Session with includes a string index signature whose properties are of type unknown. (This is what Record<string, unknown> means.) Since Session does not have an index signature, the compiler does not consider WithAdditionalParams<Session> assignable to Session.
    1. The type-fest package contains only types, meaning they are only used at compile-time and nothing is ever compiled into actual JavaScript code. This package contains functions that are compiled into JavaScript code and used at runtime.
    1. Having actual functions here is a non-goal. This package is for types only, meaning nothing ends up compiled into actual JS code.
    2. An interface can be re-opened. Whereas a type is sealed. So a solution for microsoft/TypeScript#15300 is to map the interface (which can be defined in many places) to a type.
  3. Oct 2021
    1. function applyDefaults(fetchFn: typeof fetch, defaults: Required<Parameters<typeof fetch>[1]>)
    2. In rare cases, the underlying types aren't exposed from the library. What shall we do then? Maybe we could also use the typeof operator here too and combine it with a TypeScript's built-in type Parameters. Parameters becomes useful whenever you want to extract the type of parameters from a function type:
  4. Sep 2021
    1. TypeScript is an extension of JavaScript. You can think of it as JavaScript with a few extra features. These features are largely focused on defining the type and shape of JavaScript objects. It requires that you be declarative about the code you're writing and have an understanding of the values your functions, variables, and objects are expecting.While it requires more code, TypeScript is a fantastic means of catching common JavaScript bugs while in development. And for just that reason, it's worth the extra characters.
    2. As a bonus, you have the option of choosing a particular version of JavaScript to target when compiling, so you can use updated JavaScript features, but still, maintain legacy browser support (if you're into that sort of thing)!
    1. Use this to load modules whose location is specified in the paths section of tsconfig.json when using webpack. This package provides the functionality of the tsconfig-paths package but as a webpack plug-in. Using this plugin means that you should no longer need to add alias entries in your webpack.config.js which correspond to the paths entries in your tsconfig.json. This plugin creates those alias entries for you, so you don't have to!
    1. The declarations you make in the tsconfig.json are re-stated in the webpack.config.js. Who wants to maintain two sets of code where one would do? Not me.
    2. Let's not get over-excited. Actually, we're only part-way there; you can compile this code with the TypeScript compiler.... But is that enough?I bundle my TypeScript with ts-loader and webpack. If I try and use my new exciting import statement above with my build system then disappointment is in my future. webpack will be all like "import whuuuuuuuut?"You see, webpack doesn't know what we told the TypeScript compiler in the tsconfig.json.
  5. Aug 2021
    1. which seems to resolve the issue for me and makes no casts, ensuring that Typescript can keep doing its good job of widening as much as necessary and narrowing as much as possible without me having to claim I know better than the compiler. I'm posting it here since it doesn't seem to have been mentioned anywhere.

      makes no casts, ensuring that Typescript can keep doing its good job of widening as much as necessary and narrowing as much as possible without me having to claim I know better than the compiler.

    2. I think a more natural/appropriate behavior for type signature of includes would be for the literal types to be widened.
    1. This isn't too restrictive, and provides a nice type type guard.
    2. function includes<T, U extends T>(arr: readonly U[], elem: T): elem is U { return arr.includes(elem as any); }
    3. Now consider we want to handle numbers in our known value set: const KNOWN_VALUES = Object.freeze(['a', 'b', 'c', 1, 2, 3]) function isKnownValue(input?: string | number) { return typeof(input) === 'string' && KNOWN_VALUES.includes(input) } Uh oh! This TypeScript compiles without errors, but it's not correct. Where as our original "naive" approach would have worked just fine. Why is that? Where is the breakdown here? It's because TypeScript's type system got in the way of the developer's initial intent. It caused us to change our code from what we intended to what it allowed. It was never the developer's intention to check that input was a string and a known value; the developer simply wanted to check whether input was a known value - but wasn't permitted to do so.
    4. Please read https://stackoverflow.com/questions/41750390/what-does-all-legal-javascript-is-legal-typescript-mean
    5. See #14520 for discussion of upper-bounded generics.
    1. I believe he wants to use the as const feature while still type checking that the structure matches an interface. A workaround I'd use for something like that would be interface ITest { a: number; b: string; } let foo = { a: 5, b: "Hello" } as const;
    1. the tuple() function you need can be succinctly written as: export type Lit = string | number | boolean | undefined | null | void | {}; export const tuple = <T extends Lit[]>(...args: T) => args;
    2. const list = ['a', 'b', 'c'] as const; // TS3.4 syntax type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
    3. This type of assertion causes the compiler to infer the narrowest type possible for a value, including making everything readonly.


    4. possible to tell the compiler to infer the type of a tuple of literals as a tuple of literals, instead of as, say, string[], by using the as const syntax.
    5. Or, maybe better, interpret the list as a tuple type: const list: ['a','b','c'] = ['a','b','c']; // tuple
    6. One problem is the literal ['a','b','c'] will be inferred as type string[], so the type system will forget about the specific values.
    7. t's not supposed to work with that, since by the time you do const xs = ['a','b','c'] the compiler has already widened xs to string[] and completely forgotten about the specific values.
    1. function strictIsDog<T extends Dog extends T ? unknown : never>( // like <T super Dog> candidate: Dog | T // if Dog extends T then Dog | T is T ): candidate is Dog { // compiler recognizes that Dog | T can narrow to T return "bark" in candidate; } if (strictIsDog(animal)) {} // okay if (strictIsDog(dog)) {} // okay if (strictIsDog(mixed)) {} // okay if (strictIsDog(cat)) {} // error! // ~~~ <-- Cat is not assignable to Dog
    2. If you really want to prevent people from passing in known Cat instances to isDog() you can fake up a lower-bound type parameter constraint like this:
    3. * Now it's correct within the laws of the type system, but makes zero practical sense, * because there exists no runtime representation of the type `Date & string`. * * The type system doesn't care whether a type can be represented in runtime though.

      new tag?: makes zero practical sense

      makes zero practical sense because there exists no runtime representation of the type

    4. no plans to reduce empty cases to never more aggressively to help developers exclude weird/absurd/accidental cases
    5. As a design decision, TypeScript does not collapse that type to `never` (although it could).
    6. candidate is Dog { // compiler recognizes that Dog | T can narrow to T
    7. that is, a type like {foo: never} does not itself get reduced to never even though you shouldn't be able to have a value of type {foo: never}
    8. Using the second type guard forces the user to write a more precise type and therefore manifest any nonsensical type guards that produce never, like: function silly<T extends number>(candidate: T): candidate is T & boolean { … }
    9. You can't just move 'side-ways' between unrelated types; you need to move either up or down the lattice.
    1. function isKeyOfMcuParams(x: string): x is keyof McuParams { switch (x) { case 'foo': case 'bar': case 'baz': return true; default: return false; } }
    2. Is it possible to write a user defined type guard for a keyof string type such as keyOf foo when foo is defined ONLY as a type (and not in an array)?
    1. Introduced in the perfectly named “Typescript and validations at runtime boundaries” article @lorefnon, io-ts is an active library that aim to solve the same problem as Spicery:TypeScript compatible runtime type system for IO decoding/encoding


    2. [K in keyof User]-?:
    3. It means that when having a type guard:TypeScript and JavaScript runtime are tied to the same behaviour.
    4. Inside the if statement, TypeScript will assume that amount cannot be anything else than a string, which is true also at the runtime thanks to typeof JavaScript operator.
    5. This “gap” between what we call “runtime” and “static analysis” can be filled using TypeScript Type Guards.
    6. We will see that this is not a fatality, because TypeScript is more powerful than you thought and some developers of the community are very crafty.
    1. we use a type guard here to say that, if this function returns true, any further usage of key will be of the specified type. Otherwise, it's still just a string.
    2. keyof is a keyword in TypeScript which accepts a given object type and returns a union type of its keys. These are equivalent: type StatusKey = keyof { online: string; offline: string; busy: string; dnd: string; } type StatusKey = 'online' | 'offline' | 'busy' | 'dnd'
    3. function hasKey<O>(obj: O, key: PropertyKey): key is keyof O { return key in obj }
    1. Adding to the accepted answer, if you happen to need to use a type guard against a mixin, you'll get this error too, since the is operator doesn't behave as an implements would.
    2. Regarding the error message, the predicate type must be assignable to the value type because the type guard is used to check whether a value with a less-specific type is in fact a value with a more-specific type. For example, consider this guard: function isApe(value: Animal): value is Ape { return /* ... */ } Ape is assignable to Animal, but not vice versa.
    3. If you really don't want to use any, you could use an empty interface - {} - instead:
    4. If there is no relationship between the value's type and the type in the type predicate, the guard would make no sense. For example, TypeScript won't allow a user-defined guard like this: function isString(value: Date): value is string { return typeof value === "string"; }
    5. the generic means "give me one of each function a -> Boolean" so if any of those functions doesn't exist, then the generic doesn't exist.
  6. Jul 2021
    1. In 2.8 you can use conditional types to achieve a similar effect
    2. type CReturn<C, K extends keyof C> = C extends Array<any> ? C[number] : C[K];
    3. Prior to 2.9 keyof only returned string indexes, in 2.9 this will include numeric and symbol keys.
    4. const test = new Person(TestPerson).at("name").at("name")
  7. Jun 2021
  8. basarat.gitbook.io basarat.gitbook.io
    1. Having a member in a class and initializing it like below:class Foo { x: number; constructor(x:number) { this.x = x; }}is such a common pattern that TypeScript provides a shorthand where you can prefix the member with an access modifier and it is automatically declared on the class and copied from the constructor. So the previous example can be re-written as (notice public x:number):class Foo { constructor(public x:number) { }}
    1. Almost the same applies to typescript and babel-ts. babel-ts might support JavaScript features (proposals) not yet supported by TypeScript, but it’s less permissive when it comes to invalid code and less battle-tested than the typescript parser.
  9. May 2021
  10. Jan 2021
    1. Just use import type {AnimType}... instead

      Solves error for me:

      export 'InterfaceName' was not found in
    2. Basically the typescript compiler emits no code for interfaces, so webpack can not find them in the compiled module; except when a module consists of only interfaces. In that case the module will end up completely empty and then webpack will not investigate the exports.
    1. { item1: "hello", item2: "world" }

      Valida in automatico l'oggetto passato con l'interfaccia?

      Non necessità di un'istanza o di specificare l'interfaccia dell'istanza?


  11. Nov 2020
    1. // DO NOT INLINE this variable. For backward compatibility, foundations take a Partial<MDCFooAdapter>. // To ensure we don't accidentally omit any methods, we need a separate, strongly typed adapter variable.

      I wish I understood what they meant and why this is necessary

    1. Since Typescript 3.0 this can be done with Project References.
    2. The typescript compiler will not look at the actual typescript files from lib. Instead it will only use the typescript declaration files (*.d.ts) generated when building the lib project. That's why your lib/tsconfig.json file must contain: "declaration": true,
  12. Oct 2020
    1. Emulating TypeScript functions

      YEah, but you've also got to watch the source files to recomp0ile on changes....

      "serve": "tsc -w | firebase emulators:start --only functions",

      Modified and functionally watching my stuff

    1. TypeScript provides you with the ability to use something other than React with JSX in a type safe manner.
    1. And yes, template tags cannot have TS right now.
    2. I could imagine people putting a more complex expression in an @const than we typically find in svelte expressions today, which might create more demand for those blocks to have TypeScript support, which I don't think they have now.
    1. This library is built in TypeScript, and for TypeScript users it offers an additional benefit: one no longer needs to declare action types. The example above, if we were to write it in TypeScript with useReducer, would require the declaration of an Action type: type Action = | { type: 'reset' } | { type: 'increment' } | { type: 'decrement' }; With useMethods the "actions" are implicitly derived from your methods, so you don't need to maintain this extra type artifact.
  13. Sep 2020
    1. My solution idea is just to let the compiler knows that rest is of type T, using a custom type guard function, but you could use other approaches, like a type casting: <Child {...((rest as unknown) as T)} />
    1. You can derive the TypeScript type as follows: type Person = yup.InferType<typeof personSchema>;
    1. Let's say you import { Interface } from "api/interfaces", from source file /src/views/View.ts. Typescript would then look for the module in the following paths: /src/views/api/interfaces.ts /src/api/interfaces.ts /api/interfaces.ts
    1. Extend ActionConfig interface in rfc-extended.d.ts file with new params: import * as RFC from 'react-fetching-library'; declare module 'react-fetching-library' { export interface ActionConfig { // Only new params skipAuth: boolean; params: any; }; }
  14. May 2020
    1. TypeScript will see that the a property of A & B is incompatible with that of C: Type 'A & B' is not assignable to type 'C'. Types of property 'a' are incompatible. Type 'number' is not assignable to type 'boolean | undefined'.
    2. In TypeScript 3.9, so long as every type in an intersection is a concrete object type, the type system will consider all of the properties at once.
    1. This starter takes advantage of Typescript and Emotion. This is a personal choice, and I'd encourage you to give it a shot. If you're interested in using plain ES6 and regular scss styling, see release v1 of this library.
    1. All valid JavaScript code is also TypeScript code. You might get type-checking errors, but that won't stop you from running the resulting JavaScript.
    1. Now, a couple of years later, my guidelines for JS are:

      Advices on using JavaScript from a long time programmer:

      1. Use TypeScript instead.
      2. Push as much logic to the server as possible
      3. Use a framework like Vue or React if you need front interactivity
      4. Don't skip unit tests
    1. less easy when you switch from JavaScript to TypeScript. Running TypeScript on Cloud Functions requires a compilation phase to convert the TypeScript into JavaScript so that it can be executed by the emulator. It adds a bit of a hassle

      a bit of a hassle to compile code that can be executed by the emulator

  15. Apr 2020
    1. I found that the overhead to use types in TypeScript is minimal (if any).

      In TypeScript, unlike in JS we need to specify the types:

    2. I need to specify types of input and output. But then I get speedup due to autocompletion, hints, and linting if for any reason I make a mistake.

      In TypeScript, you spend a bit more time in the variable definition, but then autocompletion, hints, and linting will reward you. It also boosts code readability

    3. TSDoc is a way of writing TypeScript comments where they’re linked to a particular function, class or method (like Python docstrings).

      TSDoc <--- TypeScript comment syntax. You can create documentation with TypeDoc

    4. ESLint does automatic code linting

      ESLint <--- pluggable JS linter:

      • mark things that are incorrect,
      • mark things that are unnecessary or risky (e.g. if (x = 5) { ... })
      • set a standard way of writing code
    5. Write a new test and the result. If you want to make it REPL-like, instead of writing console.log(x.toString()) use expect(x.toString()).toBe('') and you will directly get the result.

      jest <--- interactive JavaScript (TypeScript and others too) testing framework. You can use it as a VS Code extension.

      Basically, instead of console.log(x.toString()), you can use except(x.toString()).toBe(''). Check this gif to understand it further