Can I override types?

Short answer: no. Long answer: noooooooooooooooooooooo

There are two ways in which you can't override a type. Let's look at them both.

Types

type Animal = {
  name: string;
};

There's no way to override this type. You could create a new type using an intersection:

type Dog = Animal & {
  name: number;
};

This still doesn't give you what you want, though, but it's a little hard to see why. If you're like me, and you hover over the Dog type in VS Code, here's what you'll see.

definition uses set intersection

Unfortunately, this doesn't really tell you if TypeScript has resolved the type of field as string or number! The Prettify helper makes it clearer.

First add the helper:

type Prettify<T> = {
  [K in keyof T]: T[K];
};

Then use it:

type PrettyDog = Prettify<Dog>;

And you see

definition shows name: never

This is because when you do the intersection, TypeScript generates something like this

type Dog = {
  name: string;
} & {
  name: number;
};

Obviously name can't be both a string and a number, so TypeScript sets it to never.

I'll show a couple more examples.

/*
Results in:

type Dog = {
    name: "san francisco";
}
*/
type Dog = Animal & {
  name: "san francisco";
};

/*
Results in:

type Dog = {
    name: any;
}
*/
type Dog = Animal & {
  name: any;
};

Maybe this looks closer to overriding a type, but we haven't actually changed Animal at all. We have just created a new type.

Interfaces

You might think you can do this with interfaces because of declaration merging. But no.

// 1. name is string
interface Food {
  name: string;
}

// 2. changing name to number results in:
// Subsequent property declarations must have the same type.  Property 'name' must be of type 'string', but here has type 'number'.ts(2717)
interface Food {
  name: number;
}

One sneaky way: function overloads.

There is one very tiny way in which you can override types: function overloading plus declaration merging. Here is what that means.

If there is a function in our interface...

interface Food {
  name(a: string): void;
}

and we change its type in a subsequent declaration...

interface Food {
  // return type changed
  name(a: string): number;
}

...TypeScript will consider the second declaration to be an overload of the first. In that case, later declarations will have precedence:

const f: Food = {
  // return type is number
  name(a: string): number {
    return 123;
  },
};

const x = f.name("apple");
//    ^? number

So, with plenty of caveats and edge cases, that is one narrow way in which you can override types.