Skip to content

Commit

Permalink
feat: enhance template literal type printing (#218)
Browse files Browse the repository at this point in the history
* feat: implement template literal type printing

---------

Co-authored-by: Ben <[email protected]>
  • Loading branch information
sor4chi and kaleidawave authored Nov 10, 2024
1 parent d0a21ba commit 9088496
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
10 changes: 7 additions & 3 deletions checker/specification/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -2441,7 +2441,7 @@ fakeRead(array1)
#### Always known math

```ts
// True regardless of
// True regardless of
function func(a: number) { return a ** 0 }

func satisfies string;
Expand Down Expand Up @@ -3694,7 +3694,7 @@ type Name = "Ben"

> Should be `Expected "Hello Ben", found "test"`. See #188
- Expected string, found "test"
- Expected `Hello ${Name}`, found \"test\"

#### Template literal type specialisation

Expand Down Expand Up @@ -3751,14 +3751,18 @@ interface X {

#### Template literal types

> Last one tests printing
```ts
type Introduction = `Hello ${string}`;

const first: Introduction = "Hello Ben";
const second: Introduction = "Hi Ben";
const third: `Hiya ${string}` = "Hello Ben";
```

- Type "Hi Ben" is not assignable to type Introduction
- Type "Hello Ben" is not assignable to type `Hiya ${string}`

#### Assigning to types as keys

Expand Down Expand Up @@ -4095,7 +4099,7 @@ x.property_a satisfies number;
x.property_b
```

- No property 'property_b' on { [string]: X[keyof X & string] }
- No property 'property_b' on { [`property_${keyof X & string}`]: X[keyof X & string] }

### Readonly and `as const`

Expand Down
38 changes: 37 additions & 1 deletion checker/src/types/printing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@ pub fn print_type_with_type_arguments(
buf
}

pub fn print_inner_template_literal_type_into_buf<C: InformationChain>(
ty: TypeId,
buf: &mut String,
cycles: &mut HashSet<TypeId>,
args: GenericChain,
types: &TypeStore,
info: &C,
debug: bool,
) {
if let Type::Constant(cst) = types.get_type_by_id(ty) {
buf.push_str(&cst.as_js_string());
} else {
buf.push_str("${");
print_type_into_buf(ty, buf, cycles, args, types, info, debug);
buf.push('}');
}
}

/// Recursion safe + reuses buffer
pub fn print_type_into_buf<C: InformationChain>(
ty: TypeId,
Expand Down Expand Up @@ -469,7 +487,25 @@ pub fn print_type_into_buf<C: InformationChain>(
unreachable!()
}
},
_constructor => {
constructor => {
if let Constructor::BinaryOperator { result: result_ty, lhs, rhs, .. } = constructor
{
if *result_ty != TypeId::NUMBER_TYPE
&& !matches!(
types.get_type_by_id(*result_ty),
Type::PartiallyAppliedGenerics(_) | Type::RootPolyType(_)
) {
buf.push('`');
print_inner_template_literal_type_into_buf(
*lhs, buf, cycles, args, types, info, debug,
);
print_inner_template_literal_type_into_buf(
*rhs, buf, cycles, args, types, info, debug,
);
buf.push('`');
return;
}
}
let base = get_constraint(ty, types).unwrap();
print_type_into_buf(base, buf, cycles, args, types, info, debug);
}
Expand Down

0 comments on commit 9088496

Please sign in to comment.