Reputation: 4156
I don't know how to type Svelte 3 reactive syntax variables.
<script lang="ts">
import type { Player, Team } from "./types";
import { DEFAULT_PLAYER } from "./utils";
$: player = DEFAULT_PLAYER as Player;
$: team = { search: "Real", players: [] } as Team;
</script>
But this doesn't work:
'Team' cannot be used as a value because it was imported using 'import type'.ts(1361)
If I use this instead:
$: team = ({ search: "Real", players: [] } as Team);
the VSCode extension svelte.svelte-vscode
format it like the first one when I save.
Is this my fault?
Is there a better way to cast those reactive vars?
Upvotes: 13
Views: 6868
Reputation: 711
When working with TypeScript in 2023, it is recommended to use the satisfies
operator for better type safety. Consider the following code snippet:
<script lang="ts">
import type { Player, Team } from "./types";
import { DEFAULT_PLAYER } from "./utils";
$: player = DEFAULT_PLAYER satisfies Player;
$: team = { search: "Real", players: [] } satisfies Team;
</script>
This approach offers improved conciseness and avoids the need for redundant declarations.
Previously, I encountered issues while using the let
method, as it didn't provide strict enforcement of object properties. For instance, the following failure is correctly identified:
type A = { a: string };
let a: A;
$: a = { a: 2 };
However, the following case does not cause a type error even though it should:
type A = { a: string };
let a: A;
$: a = { a: 'a', b: 'b' };
This situation poses a significant problem, as it allows unintended properties to be added to objects.
Upvotes: 5
Reputation: 6422
<script lang="ts">
import type { Player, Team } from "./types";
import { DEFAULT_PLAYER } from "./utils";
let player: Player;
$: player = DEFAULT_PLAYER;
let team: Team;
$: team = { search: "Real", players: [] };
</script>
I'm not a fan of using as
to type cast and will avoid it at all possible. Type casting with as
can lead to runtime type errors because you're telling the compiler "this variable will always be this type, trust me".
Instead, declare your reactive variable first with the type declaration. In the above case…
<script lang='ts'>
let team: Team;
$: team = { search: "Real", players: [] }
</script>
… no type casting needed!
Upvotes: 31
Reputation: 1260
I think you should do
<script lang="ts">
import type { Player, Team } from "./types";
import { DEFAULT_PLAYER } from "./utils";
let team: Team; // added this
$: player = DEFAULT_PLAYER as Player;
$: team = { search: "Real", players: [] };
</script>
Upvotes: 2