Fundamentals 10 min read

Why ArkTS Rejects Structural Typing and What It Means for Developers

This article explains the concept of structural typing in TypeScript, contrasts it with ArkTS's nominal typing approach, provides code examples illustrating compatibility rules, and analyzes why Huawei chose to disable structural typing in ArkTS, highlighting the trade‑offs involved.

Java Architecture Stack
Java Architecture Stack
Java Architecture Stack
Why ArkTS Rejects Structural Typing and What It Means for Developers

ArkTS extends TypeScript for HarmonyOS native app development, but unlike TypeScript it does not support structural typing. The article first introduces structural typing in TypeScript, where type compatibility is determined by the actual shape of objects rather than their names.

Structural Typing in TypeScript

TypeScript’s type system is based on structural typing, meaning two types are compatible if they have the same set of properties and methods, regardless of their declared names. Core principles include:

Shape Compatibility : Types with identical members are interchangeable.

Extra Properties Allowed : Objects may have additional properties beyond those defined in a type.

Parameter Bivariance : Function parameters can be more specific or more general as long as the overall signature matches.

Object Compatibility Example

interface Point2D { x: number; y: number; }
interface Point3D { x: number; y: number; z: number; }

const point2D: Point2D = { x: 1, y: 2 };
const point3D: Point3D = { x: 1, y: 2, z: 3 };

// Assign Point3D to Point2D – allowed because Point3D contains all required members
const anotherPoint2D: Point2D = point3D;
console.log(anotherPoint2D); // { x: 1, y: 2, z: 3 }

The assignment succeeds because the target type’s shape is satisfied.

Function Compatibility Example

type Sum = (a: number, b: number) => number;
const sum: Sum = (a, b) => a + b;

const extendedSum = (a: number, b: number, c: number) => a + b + c;
// Assign extendedSum to Sum – allowed by structural typing
const newSum: Sum = (a, b) => extendedSum(a, b, 0);
console.log(newSum(1, 2)); // 3

Even though extendedSum has an extra parameter, it can be used where a Sum is expected because the required part of the signature matches.

Advantages of Structural Typing

Flexibility : Different types with the same shape can be used interchangeably.

JavaScript Compatibility : Aligns with JavaScript’s dynamic nature, easing integration with existing code.

Reduced Boilerplate : No need for explicit interfaces when shape alone suffices.

Improved Reusability : Encourages modular, maintainable code.

ArkTS’s Nominal Typing Approach

In ArkTS, type compatibility is based on nominal typing: two objects are compatible only if they share the same declared interface or class. Even if two classes or interfaces have identical members, they are considered distinct types unless they explicitly extend or implement the same declaration.

// Two classes with identical members are NOT compatible in ArkTS
class Animal { name: string; constructor(name: string) { this.name = name; } speak() { console.log(`The animal says something.`); } }
class Dog { name: string; constructor(name: string) { this.name = name; } speak() { console.log(`Woof woof!`); } }
// let a: Animal = new Dog(); // Error in ArkTS
// Two interfaces with identical members are also distinct types
interface IFly { fly(): void; }
interface IBird { fly(): void; }
// let f: IFly = { fly: () => console.log('Flying') } as IBird; // Error in ArkTS
// Class implementing an interface is still a different type when assigned back
interface IPrint { print(): void; }
class Printer implements IPrint { print() { console.log('Printing...'); } }
// let p: Printer = { print: () => console.log('Printing') } as IPrint; // Error in ArkTS

This nominal system ensures that only explicitly related types are interchangeable, providing stricter type safety.

Why ArkTS Disables Structural Typing

Potential Unexpected Compatibility : Identical shapes could mask conceptual differences, leading to bugs.

Limited Runtime Reflection : Without structural information, runtime type checks are harder.

Balancing Safety and Flexibility : Nominal typing favors safety when developers may not fully understand structural rules.

Debugging Complexity : Implicit compatibility can make tracing type‑related errors more difficult.

Performance Considerations : Nominal checks can be resolved at compile time, potentially improving runtime performance.

Huawei likely weighed these factors when deciding to omit structural typing from ArkTS, but the design remains open to future revision based on developer feedback.

HarmonyOS documentation screenshot
HarmonyOS documentation screenshot
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TypeScriptHarmonyOSArkTSStructural TypingNominal Typing
Java Architecture Stack
Written by

Java Architecture Stack

Dedicated to original, practical tech insights—from skill advancement to architecture, front‑end to back‑end, the full‑stack path, with Wei Ge guiding you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.