Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
- typeOf no longer throws
Browse files Browse the repository at this point in the history
- removed Without Type Checking example that used undocumented internals
- removed info blurb about only accepting component classes for additional safety
  • Loading branch information
MisterUncloaked committed Aug 19, 2019
1 parent 0d52578 commit 666d7a9
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 38 deletions.
29 changes: 5 additions & 24 deletions docs/advanced/type-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ In certain situations, such as when building reusable and customizable component

To facilitate safer development for these kinds of situations, Roact provides the `Roact.typeOf` and `Roact.isComponent` functions to help validate these objects.

## Without Type Validation
## Roact Object Type Validation

Suppose we want to write a `Header` component with a prop for the title child element:
```lua
Expand All @@ -19,23 +19,7 @@ function Header:render()
end
```

Now suppose we want to validate that `title` is actually an element using [validateProps](../../api-reference/#validateprops). Without a type checking function, `title` must be queried to check for characteristics of an element:
```lua
Header.validateProps = function()
local title = props.title

if title.component then
return true
end

return false, tostring(Header) .. " prop title is not an element"
end
```
This approach is fragile, since it relies on undocumented internals.

## Roact Object Type Validation

With `Roact.typeOf` we can be certain we have a Roact Element:
Now suppose we want to validate that `title` is actually an element using [validateProps](../../api-reference/#validateprops). With `Roact.typeOf` we can be certain we have a Roact Element:
```lua
Header.validateProps = function()
local title = props.title
Expand All @@ -44,7 +28,7 @@ Header.validateProps = function()
return true
end

return false, tostring(Header) .. " prop title is not an element"
return false, "prop title is not an element"
end
```

Expand All @@ -62,7 +46,7 @@ Header.validateProps = function()
return true
end

return false, tostring(Header) .. " prop title can not be an element"
return false, "prop title can not be an element"
end

function Header:render()
Expand All @@ -75,7 +59,4 @@ function Header:render()
})
})
end
```

!!! info
Because strings (hosts) and functions are valid component types, `Roact.isComponent` is less safe than `Roact.typeOf`. If safety is paramount, consider only allowing component classes, and checking that the `typeOf` the prop is `Roact.Type.StatefulComponentClass`.
```
2 changes: 1 addition & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ end
Roact.typeOf(roactObject) -> Roact.Type
```

Returns the [Roact.Type](#roacttype) of the passed in Roact object
Returns the [Roact.Type](#roacttype) of the passed in Roact object, or `nil` if the input is not a Roact object.

---

Expand Down
4 changes: 4 additions & 0 deletions src/Type.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ function TypeInternal.of(value)
end

function TypeInternal.nameOf(type)
if typeof(type) ~= "userdata" then
return nil
end

return TypeNames[type]
end

Expand Down
6 changes: 0 additions & 6 deletions src/TypeMirror.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ local Mirror = {
end,
}

setmetatable(Mirror, {
__tostring = function()
return "TypeMirror"
end
})

strict(Mirror, "TypeMirror")

return Mirror
14 changes: 7 additions & 7 deletions src/TypeMirror.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ return function()
end)

describe("typeOf", function()
it("should throw if the value is not a valid type", function()
expect(pcall(Mirror.typeOf, 1)).to.equal(false)
expect(pcall(Mirror.typeOf, true)).to.equal(false)
expect(pcall(Mirror.typeOf, "test")).to.equal(false)
expect(pcall(Mirror.typeOf, print)).to.equal(false)
expect(pcall(Mirror.typeOf, {})).to.equal(false)
expect(pcall(Mirror.typeOf, newproxy(true))).to.equal(false)
it("should return nil if the value is not a valid type", function()
expect(Mirror.typeOf(1)).to.equal(nil)
expect(Mirror.typeOf(true)).to.equal(nil)
expect(Mirror.typeOf"test").to.equal(nil)
expect(Mirror.typeOf(print)).to.equal(nil)
expect(Mirror.typeOf({})).to.equal(nil)
expect(Mirror.typeOf(newproxy(true))).to.equal(nil)
end)

it("should return the assigned type", function()
Expand Down

0 comments on commit 666d7a9

Please sign in to comment.