Luau "Humanoid: Humanoid" being weird? Linter: "Type 'Instance' could not be converted into 'Humanoid'"

raw text
--!strict

game.Players.PlayerAdded:Connect(function(AddedPlayer: Player)

	AddedPlayer.CharacterAdded:Connect(function(NewChar: Model)
		
		local Humanoid: Humanoid = NewChar:WaitForChild("Humanoid")
		
		Humanoid.Died:Connect(function()
			AddedPlayer:LoadCharacter()
		end)
	
	end)

	AddedPlayer:LoadCharacter()
end)

I’m trying to get better at using Luau features
Is line 7 supposed to be underlined like that?
Type 'Instance' could not be converted into 'Humanoid'

Original Post

I’m trying to get better at using Luau.
Is that Humanoid variable supposed to be underlined in orange?

Is there something wrong with my code, or is it just a minor thing with the code editor?

code raw text
game.Players.PlayerAdded:Connect(function(AddedPlayer: Player)
	
	AddedPlayer.CharacterAdded:Connect(function(NewChar: Model)
		local Humanoid: Humanoid = NewChar:FindFirstChildOfClass("Humanoid")
		
		Humanoid.Died:Connect(function()
			AddedPlayer:LoadCharacter()
		end)
		
	end)
	
	AddedPlayer:LoadCharacter()
end)
1 Like

What’s the warning? You might wanna do Humanoid? instead as it might think that it would return nil.

game.Players.PlayerAdded:Connect(function(AddedPlayer)
	
	AddedPlayer.CharacterAdded:Connect(function(NewChar)
		local Humanoid = NewChar:FindFirstChildOfClass("Humanoid")
		
		Humanoid.Died:Connect(function()
			AddedPlayer:LoadCharacter()
		end)
		
	end)
	
	AddedPlayer:LoadCharacter()
end)

Find methods can return nil so you ideally should add a question mark; this will get rid of the underline for your Humanoid declaration but one will appear under Died because nil has no properties, therefore both Humanoid.Died and nil.Died can’t both be satisfied.

If you check the existence of a Humanoid, underline goes. You should be doing this with or without typechecking to begin with rather than assuming that a find method returns a non-nil value.

if Humanoid then
    -- Your Died connection goes here
end
2 Likes

I’m used to using WaitForChild for things like this, so I totally forgot about waiting for the object to load
in. I changed the code while messing with it, and forgot to change it back.

This code seems to satisfy the linter

--!strict

game.Players.PlayerAdded:Connect(function(AddedPlayer: Player)

	AddedPlayer.CharacterAdded:Connect(function(NewChar: Model)
		
		NewChar:WaitForChild("Humanoid")
		
		local Humanoid: Humanoid | nil = NewChar:FindFirstChildOfClass("Humanoid")
		
		if Humanoid then
			Humanoid.Died:Connect(function()
				AddedPlayer:LoadCharacter()
			end)
		end

	end)

	AddedPlayer:LoadCharacter()
end)

though it’s arguably less efficient than just

--!strict

game.Players.PlayerAdded:Connect(function(AddedPlayer: Player)

	AddedPlayer.CharacterAdded:Connect(function(NewChar: Model)
		
		local Humanoid: Humanoid = NewChar:WaitForChild("Humanoid")
		
		Humanoid.Died:Connect(function()
			AddedPlayer:LoadCharacter()
		end)
	
	end)

	AddedPlayer:LoadCharacter()
end)

Where do I add the question mark?

I’ve updated the original post to be more clear.

I found a solution that I don’t think is terrible!

--!strict

game.Players.PlayerAdded:Connect(function(AddedPlayer: Player)

	AddedPlayer.CharacterAdded:Connect(function(NewChar: Model)
		
		local Humanoid : Humanoid = NewChar:WaitForChild("Humanoid") :: Humanoid
		
		Humanoid.Died:Connect(function()
			AddedPlayer:LoadCharacter()
		end)
	
	end)

	AddedPlayer:LoadCharacter()
end)
5 Likes

Also, by the way, to make it even cleaner, the type annotation on the variable is unnecessary since you’re already asserting that it’s a Humanoid via the type assertion operator ::

3 Likes

Will that affect performance in the future though?

No. There is a difference between local x: y = z and local x = z :: y. In some cases you’ll want to leave it to type inference (e.g local x = 2 – Luau can already infer that the value on the right hand side is a number). In this case you’re already asserting the type of the value therefore unnecessary to add a type annotation.

1 Like

I think I’ll leave it, in the event that Luau becomes more like C#

there might be a reason it’s done like that
I know C# is more of a compiled language, where Luau is interpreted, but meh, doesn’t hurt to leave it in

On second thought, I probably can’t predict the syntax changes if Luau becomes more of a compiled language. You’re right, there’s no real practical difference.