2023-05-05
1571
#typescript
Temitope Oyedele
168584
111
May 5, 2023 â‹… 5 min read

Getting started with the TypeScript satisfies operator

Temitope Oyedele I am a web developer and technical writer. I love to write about things I've learned and experienced.

Recent posts:

Building a Full-Featured Laravel Admin Dashboard with Filament

Building a full-featured Laravel admin dashboard with Filament

Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.

Kayode Adeniyi
Dec 20, 2024 â‹… 5 min read
Working With URLs In JavaScript

Working with URLs in JavaScript

Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.

Joe Attardi
Dec 19, 2024 â‹… 6 min read
Lazy Loading Vs. Eager Loading

Lazy loading vs. Eager loading

In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.

Njong Emy
Dec 18, 2024 â‹… 5 min read
Deno logo over an orange background

How to migrate your Node.js app to Deno 2.0

Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]

Yashodhan Joshi
Dec 17, 2024 â‹… 7 min read
View all posts

One Reply to "Getting started with the TypeScript <code>satisfies</code> operator"

  1. It was good that you took the original version of this article down following my critique of it, but sad to say, the new version is still very flawed. You still don’t fully understand the use of the satisfies operator, and indeed how TypeScript type inference works in general, though at least you now understand that satisfies is a compile-time feature, and has no relevance at run time.

    The first example is a correct use of satisfies, but you totally misunderstand why; the second is contrived in a way that makes it LESS type safe than it should be (and once that’s corrected, is a really weak argument for using satisfies anyway), and the third and fourth examples simply don’t require satisfies at all.

    In example 1, you say:

    “Thanks to the satisfies operator;[sic] TypeScript knows that our birthState is a string and not an object because it has prevalidated/checked the values of all properties of the User.”

    No, satisfies is NOT the reason the compiler knows the type of birthState! The code compiles because you removed the type from the variable, allowing the compiler to infer the type of the object from the values used in its creation. The compiler knows that user.birthState is a string because it just saw it being initialized! You can remove the satisfies clause (and indeed the type User), and the code will still compile. If you think about, all you’re saying with the satisfies is that birthState must be a MyState, so it will catch errors like giving birthState a numeric value, but that has nothing to do with why your example compiles.

    The second example is valid, but its contrived nature means you’re actually ending up with LESS type safety than with how you’d typically write this code. By using the Record type, you’re preventing the compiler from doing the obvious checks on the properties. A correct version of this example would be:

    type Student = { FirstName: string; LastName: string; age: number; school: string; email: string };
    const student = {
    FirstName: “Temitope”,
    LastName: “Oyedele”,
    age: 36,
    school: “oxford”,
    } satisfies Partial;
    student.FirstName.toLowerCase();
    student.age.toFixed();

    Here, you get the benefit of type checking on the individual properties, with your desire to allow a partial definition. In your original, you unnecessarily hamper the compiler’s ability to check your code.

    Once you get rid of the Record, it’s also not obvious to me that using satisfies gains you anything over the more idiomatic convention of making email an optional property, because Partial is really TOO permissive in most cases:

    type Student = { FirstName: string; LastName: string; age: number; school: string; email?: string };
    const student: Student = {
    FirstName: “Temitope”,
    LastName: “Oyedele”,
    age: 36,
    school: “oxford”,
    };

    There’s a similar but greater problem with the third example. You’re again losing the type checking on the individual properties, while gaining nothing from using satisfies. In practice, you’d write this example:

    type Student = { FirstName: string; LastName: string; age: number; school: string };
    const student: Student = {
    FirstName: “Temitope”,
    LastName: “Oyedele”,
    age: 36,
    school: “oxford”,
    };
    student.age.toFixed();
    student.school.toLowerCase();

    That will allow the compiler to flag extra or missing properties, or type errors on the properties themselves, with no need for satisfies at all.

    Just for completeness’ sake, the fourth example is also a non-use case for satisfies. It does nothing that this long-correct code wouldn’t achieve:

    type Book = { title: string, author: string, year: number };

    const library: Record = {
    book1: { title: “Things fall apart”, author: “Chinua Achebe”, year: 1958 },
    book2: { title: “Lord of the flies”, author: “William Golding”, year: 1993 },
    book3: { title: “Harry Potter”, author: “J.k Rowling”, year: “1997” }, // Error
    };

    I think the best way to summarize the *correct* use of satisfies is that it gives a degree of type-checking on an object, without removing the specific type inference that allows the compiler to validate later operations on it. At best, your examples and the explanations of them only partially reflect this.

    On a more general note, the article again shows a lack of attention to detail: inconsistency in the use of ‘ vs. ” for strings, inconsistency in the case of property names, a typo in “Detroit”. You should install one of the popular lint tools, and perhaps use an IDE that includes a spell checker, such as WebStorm.

Leave a Reply