skip to content

In Dart, what do `part` and `part of` do, how does a part differ from a separate library, and when is a `library` directive needed?

level: middleimportance: should knowfreq 30%

answer

  1. one library, several files
  2. shared imports and privacy
  3. part of takes a URI string
  4. small libraries preferred
  5. library; for docs and annotations

basics

~20 s

part splits one library across files: a part file shares its owner's imports, namespace and private names. The part of directive should name its owner by URI string. A library directive is now only needed to attach library-level docs or annotations.

solid answer

~40 s

`part 'cart_items.dart';` in `cart.dart` and `part of 'cart.dart';` at the top of the other file make them **one library**: one namespace, one set of imports declared in the owner, and shared underscore privacy. A separate library, by contrast, has its own imports and sees only the other's public names. Effective Dart asks for a **URI string** in `part of` (lint `use_string_in_part_of_directives`) rather than a library name, and the Dart team recommends small libraries over parts for hand-written code; parts survive mainly for generated code. Since Dart 2.19 a `library;` directive can be unnamed: you still need it to hang a library-level doc comment or an annotation such as `@TestOn('browser')`. Naming libraries is legacy and discouraged.

code

dart · 21 lines
dart
// cart.dart
/// Shopping cart domain model.
library;

import 'dart:math' as math; // also used by cart_items.dart

part 'cart_items.dart';

class Cart {
  final _items = <_Line>[];
  int get count => _items.length;
}

// cart_items.dart
part of 'cart.dart';

class _Line {
  _Line(this.sku, int qty) : qty = math.max(1, qty);
  final String sku;
  final int qty;
}

go deeper

for a junior

Recall that part and part of join files into one library and that every Dart file is already a library without a directive.

for a middle

Explain what a part shares with its owner: namespace, imports and privacy; that part of takes a URI; and what library; is for.

for a senior

Push hand-written code toward small libraries and keep parts for generated code, enforcing URI-based part of with lints.

for a principal

Set a codebase rule on parts versus mini-libraries that balances private sharing against explicit per-file dependencies.

## Parts: one library, several files A Dart **library** is normally a single file. The `part` directive lets one library span several files: - the **owner** file lists its parts: `part 'cart_items.dart';` - each **part file** begins with `part of 'cart.dart';`, naming its owner. After that, the files behave as one unit: 1. They share **one top-level namespace**; a class declared in the part is used in the owner without any import. 2. They share **privacy**: `_helper` in the owner is visible in the part and vice versa, because privacy is library-level. 3. They share **imports**: in Dart 3.13 a part file cannot declare its own `import` directives; every import the part needs is written in the owner. A separate library behaves differently on each point: it has its own namespace, must import what it uses, and sees only the other library's public names. | Aspect | `part` file | Separate library | |---|---|---| | Namespace | the owner's | its own | | `_private` names of the other file | visible | invisible | | Where its imports go | in the owner | in itself | | Importable on its own | no | yes | ## Naming the owner: use a URI `part of` accepts either a URI string or a **library name**. Effective Dart says to use the string, and the `use_string_in_part_of_directives` lint in `package:lints`' core set enforces it. Library names are a legacy feature that can be ambiguous when working out which library a part belongs to; the URI points straight at the file. ## When to use parts at all The dart.dev packages guide is direct: the Dart team **doesn't recommend** parts for organising hand-written code. It prefers many small libraries, one class per library unless classes are tightly coupled, so each file declares its own dependencies. Many developers avoid `part` entirely because a one-file library is easier to reason about. Parts remain common for one purpose: incorporating **generated code** into a library, so that generated members can see the library's private declarations. How those generated files are produced belongs to the code-generation tooling, not to this topic. If you want "friend" access between two hand-written classes, the simpler choice is often to put both in one file rather than splitting them into parts. ## The `library` directive today Every file is a library whether or not it has a `library` directive. The directive is now needed only to attach things to the library as a whole: - a **library-level doc comment**, which `dart doc` places on the library page; - **annotations** that apply to the library, such as `@TestOn('browser')` in a test or `@Deprecated(...)`. Since **Dart 2.19** the directive can be **unnamed**: `library;`. Writing a name (`library my_lib;`) is still accepted but discouraged: Effective Dart's style guide says not to name libraries, and the `unnecessary_library_name` lint in the recommended set flags it. A part owner does not need a `library` directive, because the part names it by URI. ## Rules of thumb - Split code into small libraries first; reach for `part` only when files must share privacy, usually because a tool generates one of them. - Always write `part of '<owner>.dart';`, never a library name. - Put every import a part needs in its owner. - Use `library;` only to carry a library doc comment or annotation.

  • In Dart, why does Effective Dart prefer `part of 'cart.dart';` over `part of cart;`?
    A library name is a legacy, optional label that several libraries could share, so tools may not know which library a part belongs to. A URI string points directly at the owning file and cannot be ambiguous; the `use_string_in_part_of_directives` lint enforces it.
  • In Dart, can a part file be imported directly by another library?
    No. A part is not a library on its own; importing it is an error. Other code imports the owning library, which exposes the part's public declarations as part of its namespace.

saying these in an interview costs you the question

  • A part file declares its own imports
  • part files have their own private namespace
  • part of should name the library, as in part of cart;
  • Every Dart file needs a library directive to be a library
  • The Dart team recommends parts for splitting hand-written code