Skip to content

Commit

Permalink
feat: @type intrinsic (#7151)
Browse files Browse the repository at this point in the history
Closes #7150

Adds for the new `@type` intrinsic function. This function can be passed a type, and it will give you back an object (`std.reflect.Type`) with information about it -- for example, whether it's a struct or class, what properties or fields it has, etc. You can use this to validate request data structures at runtime, generate schemas for APIs or databases, or for simply asserting on the structure of your code.

Future work:
- Support doc reflection
- Fix support for variadic functions
- Open discussion about accessing private fields or methods via reflection
- Open issue about explicit "preflight" annotation
- Open issue about explicit `TypeId` enum

## Checklist

- [x] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted)
- [x] Description explains motivation and solution
- [x] Tests added (always)
- [x] Docs updated (only required for features)
- [x] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
Chriscbr authored Sep 28, 2024
1 parent bca2b7c commit ef582e7
Show file tree
Hide file tree
Showing 284 changed files with 3,971 additions and 145 deletions.
66 changes: 66 additions & 0 deletions docs/by-example/36-reflection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Type reflection
id: type-reflection
slug: /type-reflection
sidebar_label: Type reflection
description: Type reflection
keywords: [Wing language, Type reflection]
image: /img/wing-by-example.png
---

The `@type` intrinsic function returns a reflection of the type passed to it.

You can access its `.kind` property to get the kind of the type, and use various helper methods like `.asStruct()`, `.asClass()`, `.asInterface()`, etc. to access related properties.

```js playground example title="main.w"
let generateJsonSchema = (structType: std.reflect.Type): str => {
if let st = structType.asStruct() {
let schema = MutJson {
type: "object",
properties: {},
required: []
};

for name in st.fields.keys() {
let fieldSchema = MutJson {};
let var field = st.fields[name].child;
let var required = true;
if let opt = field.asOptional() {
required = false;
field = opt.child;
}

if field.kind == "str" {
fieldSchema["type"] = "string";
} else if field.kind == "num" {
fieldSchema["type"] = "number";
} // ...handle other types

schema["properties"][name] = fieldSchema;
if required {
// TODO: https://github.com/winglang/wing/issues/6929
unsafeCast(schema["required"])?.push(name);
}
}

return Json.stringify(schema);
}

throw "input must be a struct type";
};

struct User {
name: str;
age: num;
email: str?;
}

log(generateJsonSchema(@type(User)));
```
```bash title="Wing console output"
# Run locally with wing console
{"type":"object","properties":{"age":{"type":"number"},"email":{"type":"string"},"name":{"type":"string"}},"required":["age","name"]}
```
2 changes: 2 additions & 0 deletions packages/@winglang/sdk/src/std/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export * from "./string";
export * from "./struct";
export * from "./test";
export * from "./test-runner";

export * as reflect from "./reflect";
1 change: 1 addition & 0 deletions packages/@winglang/sdk/src/std/reflect/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./type";
Loading

0 comments on commit ef582e7

Please sign in to comment.